home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-03 / qbnws102.zip / QBNWS102.NWS < prev    next >
Text File  |  1990-02-02  |  113KB  |  2,891 lines

  1.      Volume  1, Number  2                                 February  2, 1990
  2.  
  3.      
  4.      
  5.      
  6.      
  7.      
  8.      
  9.      
  10.      
  11.      
  12.      
  13.      
  14.                    **************************************************
  15.                    *                                                *
  16.                    *                    QBNews                      *
  17.                    *                                                *
  18.                    *      International QuickBASIC Electronic       *
  19.                    *                  Newsleter                     *
  20.                    *                                                *
  21.                    *    Dedicated to promoting QuickBASIC around    *
  22.                    *                  the world                     *
  23.                    *                                                *
  24.                    **************************************************
  25.      
  26.      
  27.      
  28.      
  29.      
  30.      
  31.      
  32.      
  33.      
  34.      
  35.      
  36.      
  37.      
  38.      
  39.      
  40.      
  41.         The  QBNews  is  an electronic newsletter  published  by  Clearware
  42.      Computing. It can be freely distributed providing NO CHARGE is charged
  43.      for  distribution.  The  QBNews is copyrighted in  full  by  Clearware
  44.      Computing.  The  authors  hold  the  copyright  to  their   individual
  45.      articles.  All program code appearing in QBNews is released  into  the
  46.      public  domain.   You  may  do what you  wish  with  the  code  except
  47.      copyright  it.  QBNews  must  be  distributed  whole  and  unmodified.
  48.      
  49.      You can write The QBNews at:
  50.      
  51.           The QBNews
  52.           P.O. Box 507
  53.           Sandy Hook, CT 06482
  54.      
  55.      Copyright (c) 1989 by Clearware Computing.
  56.      
  57.      
  58.      
  59.      The QBNews                                                   Page    i
  60.      Volume  1, Number  2                                 February  2, 1990
  61.  
  62.  
  63.      ----------------------------------------------------------------------
  64.  
  65.                         T A B L E   O F   C O N T E N T S
  66.  
  67.      
  68.      1.  From the Editors Desk
  69.           With a future so bright, I got to wear shades ... ............  1
  70.  
  71.      2.  Mail Bag
  72.           Mail From Our Readers ........................................  2
  73.  
  74.      3.  Algorithms
  75.           Fast String Searching in QuickBASC by Ethan Winer ............  4
  76.           Reversing INSTR by Larry Stone ...............................  6
  77.  
  78.      4.  Who ya gonna call? CALL INTERRUPT
  79.           Using the PSP by Hector Plasmic ..............................  9
  80.  
  81.      5.  Product Announcements
  82.           Microsoft Professional BASIC 7.0 ............................. 13
  83.           Index Manager   CDP Consultants .............................. 15
  84.           MicroHelp Library Manager .................................... 16
  85.  
  86.      6.  The Tool Shed
  87.           Update on MicroHelp's QB Optimizer Package by  Larry Stone ... 19
  88.  
  89.      7.  Ask MR. WIZZARD
  90.           Mr. Wizard tells what "Bytes Free" means ..................... 20
  91.  
  92.      8.  Graphically Speaking
  93.           Getting and Putting Graphics by Frederick Volking ............ 22
  94.  
  95.      9.  And I Heard it Through the Grapevine
  96.           Exerpts from the QUIK_BAS echo ............................... 30
  97.  
  98.      10.  Some Assembly Required
  99.           Retuning Errorlevels to QB by Harold Thomson ................. 34
  100.  
  101.      11.  Swap Shop
  102.           Extended Key Codes ........................................... 39
  103.           Menus ........................................................ 43
  104.  
  105.      12.  Input Past End
  106.           Contacting the QBNews ........................................ 47
  107.  
  108.      The QBNews                                                   Page   ii
  109.      Volume  1, Number  2                                 February  2, 1990
  110.  
  111.  
  112.  
  113.      ----------------------------------------------------------------------
  114.                     F r o m   t h e   E d i t o r s   D e s k
  115.      ----------------------------------------------------------------------
  116.  
  117.      The Future of the QBNews by David Cleary
  118.      
  119.           With  this issue, I can say I am actually proud. The support  you
  120.      have  shown  has been overwhelming. I just feel that  this  newsletter
  121.      will  take  off because the better it gets, the more support  it  will
  122.      receive. The more support it receives, the better it will get. It's  a
  123.      viscous circle.
  124.      
  125.           I  have received some very nice letters from people. Two of  them
  126.      are  in our Mailbag section. I would like to here suggestions on  what
  127.      you  would like to see in this newsletter. With every issue,  we  will
  128.      continue  to evolve to suit the needs of the QuickBASIC programmer.  I
  129.      do feel that this issue does not address the needs of the beginner.  I
  130.      would  like  to see a section devoted to beginners so if  anybody  out
  131.      there has some ideas, please contact me.
  132.      
  133.           I am also thinking of making the QBNews available on disk. If you
  134.      are  interested in receiving it on disk, for a nominal charge, let  me
  135.      know. If enough would like it this way I may institute it for the next
  136.      issue.  Also, if you write me, I would be interested in knowing  where
  137.      you got your issue.
  138.      
  139.           One  final  note.  I  would  like  this  newsletter   distributed
  140.      internationally, specifically England and Australia. If you run a  BBS
  141.      in  either of these countries, I would be interested in  hearing  from
  142.      you. I would be willing to upload it to your board. If anybody outside
  143.      of  the  USA or Canada is reading this, I want to here from  you.  I'd
  144.      like  to  know that this is being distributed as widely  as  possible.
  145.      Until April, goodbye.
  146.      
  147.      David Cleary
  148.      
  149.  
  150.  
  151.  
  152.  
  153.  
  154.  
  155.  
  156.  
  157.  
  158.  
  159.  
  160.  
  161.  
  162.  
  163.  
  164.  
  165.  
  166.  
  167.  
  168.      The QBNews                                                     Page  1
  169.      Volume  1, Number  2                                 February  2, 1990
  170.  
  171.  
  172.  
  173.      ----------------------------------------------------------------------
  174.                                  M a i l   B a g
  175.      ----------------------------------------------------------------------
  176.  
  177.      
  178.      Dear Mr. Cleary,
  179.      
  180.           Your  news  letter  is  a great idea,  please  continue  it.  The
  181.      programs  were,  also,  very informative and useful.  In  the  section
  182.      describing the program, SCRNSUBS.BAS, you make this statement.
  183.      
  184.           "The  only  problem  when using internal QB routines  is  that  I
  185.      haven't found a way to use them in the environment."
  186.      
  187.           I  have found a way by making a Quick Library with  the  routine.
  188.      The routine will only work if you include the DECLARE statement in the
  189.      module.
  190.      
  191.      Examples:      DECLARE SUB MemCopy ALIAS "B$ASSN" (BYVAL...
  192.      
  193.                     DEFINT A-Z
  194.                     SUB ScrSave (Buffer(), Page) STATIC
  195.                     .
  196.                     .
  197.                     END SUB
  198.      
  199.      Compile:       BC SCRSAVE/O;
  200.                     LINK /Q SCRSAVE, SCRSAVE.QLB,, BQLB45.LIB;
  201.      
  202.      Environment:   A DECLARE statement is not needed, just make your
  203.                     calls.
  204.      
  205.                     Call ScrSave(Buffer(), Page)
  206.      
  207.      
  208.      Gaylon Hill
  209.      Louisville, TN
  210.      
  211.      [EDITOR'S NOTE]
  212.      
  213.           It seems that the simplest way is the one that works. I was  busy
  214.      trying a bunch of convoluted ways to do it with no luck at all. Thanks
  215.      for sharing this with us.  David Cleary
  216.      
  217.      
  218.      Dear Mr. Cleary,
  219.      
  220.           I just read your QBNews Vol 1 No 1 which I picked off the  Probas
  221.      BBS. Great idea. I am like most other BASIC programmers, no  training,
  222.      ever.  However, I am interested in the things that interrupts can  do.
  223.      The  catch is, I really don't understand what an interrupt is  ect.  I
  224.      can  duplicate  Hector's code but that's about it. How  about  getting
  225.      Hector  to write a little about interrupts and what they are and  what
  226.      the terminology means.
  227.      
  228.      
  229.      The QBNews                                                     Page  2
  230.      Volume  1, Number  2                                 February  2, 1990
  231.  
  232.      John F. Farrell
  233.      Mesquite, TX
  234.      
  235.      [HECTOR'S RESPONSE]
  236.      
  237.           I'm  not gonna go all techie on you here, so relax.  But what  is
  238.      an interrupt anyway?  About what the name implies.  When an  interrupt
  239.      occurs, the central processing unit (CPU) "interrupts" what it's doing
  240.      and  transfers  control  to  an interrupt  handler.   The  handler  is
  241.      responsible  for  determining the cause of the  interrupt  and  taking
  242.      appropriate action, then returning control to the interrupted process.
  243.      
  244.           The CPU knows where the interrupt handlers are located by looking
  245.      up  their  addresses  in  special sections  of  memory  known  as  the
  246.      interrupt  vector table.  In this way an interrupt can be replaced  or
  247.      chained.
  248.      
  249.           Software interrupts, the ones we're using in this column, can  be
  250.      triggered by any program by using the INT instruction (QuickBASIC does
  251.      that  for you when you use CALL INTERRUPT).  Interrupt 21h is the  MS-
  252.      DOS  function dispatch interrupt, which provides easy access  to  many
  253.      operating system functions not directly available through  QuickBASIC.
  254.      Other interrupts can also be useful, notable 10h (for IBM-compatibles)
  255.      for video, 13h for disk control, 16h for the keyboard, and so forth.
  256.      
  257.           There  are several readily available books covering  the  various
  258.      MS-DOS and BIOS interrupts, and an excellent file (in archive  format)
  259.      called  INTER489  from Ralf Brown (1:129/46 at last report)  if  you'd
  260.      like to learn more about them.
  261.      
  262.      Hector Plasmic
  263.      
  264.  
  265.  
  266.  
  267.  
  268.  
  269.  
  270.  
  271.  
  272.  
  273.  
  274.  
  275.  
  276.  
  277.  
  278.  
  279.  
  280.  
  281.  
  282.  
  283.  
  284.  
  285.  
  286.  
  287.      The QBNews                                                     Page  3
  288.      Volume  1, Number  2                                 February  2, 1990
  289.  
  290.  
  291.  
  292.      ----------------------------------------------------------------------
  293.                                A l g o r i t h m s
  294.      ----------------------------------------------------------------------
  295.  
  296.      FAST STRING SEARCHING IN QUICKBASIC by Ethan Winer
  297.      
  298.           A wise programmer once said, "You can never write a sort  routine
  299.      that's  fast enough or small enough."  No doubt, this same  philosophy
  300.      holds  true  for string searching routines.  Therefore,  I  was  quite
  301.      interested  to see an article in the July/August  Programmers  Journal
  302.      which  presented  an  assembly language  version  of  the  Boyer-Moore
  303.      searching algorithm.  Compared to some of the other implementations  I
  304.      had  seen,  this one appeared to be very tight and  well  coded.  I've
  305.      written a few searching routines myself to use with QuickBASIC  string
  306.      arrays,  and was very eager to see how much faster this  "new"  method
  307.      would be.
  308.      
  309.           After  carefully  modifying  the printed  routine  to  work  with
  310.      QuickBASIC  4.5,  I  devised  a short test program  to  time  it.   My
  311.      benchmark  searched a 10,000 character string in a loop, and  compared
  312.      two  algorithms  -- the Boyer-Moore routine published  in  Programmers
  313.      Journal, and QuickBASIC's built-in INSTR function.  However, based  on
  314.      the  results  I obtained, it appears that the  Boyer-Moore  method  is
  315.      little  more than a mathematical curiosity.  Indeed, it was only  half
  316.      as fast as QuickBASIC!
  317.      
  318.      HOW QUICKBASIC DOES IT
  319.      
  320.           So  how  does  QuickBASIC  search  strings  so  fast?   A   quick
  321.      examination  under Microsoft CodeView reveals a fundamentally  simple,
  322.      yet  elegant  algorithm.   I have adapted  QuickBASIC's  method  (with
  323.      permission from Microsoft), and named it SearchString.  This is  shown
  324.      in Listing 1.  Please understand that this routine is not intended for
  325.      use  with  QuickBASIC.   Rather, it is to  provide  a  foundation  for
  326.      achieving BASIC's high performance in other high-level languages.   If
  327.      you  do intend to try SearchString with QuickBASIC, bear in mind  that
  328.      it  has been designed as a function, and therefore must  be  declared.
  329.      Assembler  functions were added to QuickBASIC beginning  with  version
  330.      4.00,  and they are one of the most important features that  Microsoft
  331.      has added to the language.
  332.      
  333.           Three  passed  parameters are required to  specify  the  starting
  334.      character,  the string being searched, and the sub-string  to  locate.
  335.      Even though this version uses the same basic algorithm as  QuickBASIC,
  336.      it  is slightly faster because it does not check for an illegal  Start
  337.      parameter.  Also, the start variable is passed "by value", rather than
  338.      by  address  which is the method used by  most  high-level  languages.
  339.      This  eliminates  an extra step of locating the  variable  within  the
  340.      assembler routine, thus saving a few bytes and clock cycles.
  341.      
  342.           Rather  than  relying  on a purely "brute  force"  approach  that
  343.      compares every character in both strings, QuickBASIC instead  isolates
  344.      the  first  character. In this case, it is loaded into AL.   Then  the
  345.      8088's  speedy Scasb instruction is used to find the first  occurrence
  346.      where  a possible match might begin.  The beauty of this  approach  is
  347.      
  348.      The QBNews                                                     Page  4
  349.      Volume  1, Number  2                                 February  2, 1990
  350.  
  351.      twofold  --  Scasb  is  the fastest way  to  find  a  single  matching
  352.      character,  and  subsequent searches then require comparing  one  less
  353.      character in each string.
  354.      
  355.           SearchString begins by obtaining the starting character offset in
  356.      the string being searched.  Even though most situations would  require
  357.      searching  the  entire string, being able to resume a  search  in  the
  358.      middle  of the string is often valuable.  Next, SI and DI  are  loaded
  359.      with  the  address of the first character in each string,  and  CX  is
  360.      assigned  the  number of characters to search.  Unlike  C  or  Pascal,
  361.      BASIC maintains a string descriptor which tells how long a string  is,
  362.      and   where   in  near  memory  its  data  is  located.    The   final
  363.      initialization steps are to adjust DI to point to the correct  portion
  364.      of the string being searched, and to load AL with the first  character
  365.      of the string to find.
  366.      
  367.           The  main  loop begins at the Scan label, and ends at  the  label
  368.      Found.   When Scasb finds a character that matches the one in AL,  the
  369.      remaining  characters  in both strings are compared.  If  a  match  is
  370.      found,  SearchString returns to the caller with AX holding the  offset
  371.      into  the source string.  Otherwise, Scasb is used again to  find  the
  372.      next occurrence of the first character.  This is repeated until either
  373.      the search string is located, or the source string is exhausted.
  374.      
  375.      ADAPTING THE ROUTINE TO OTHER LANGUAGES
  376.      
  377.           SearchString  may  be  easily modified to work  with  C,  Pascal,
  378.      assembly  language,  or whatever by simply changing  how  the  various
  379.      registers are initially loaded. For example, the length of a string in
  380.      Pascal  is  stored  in the byte that  precedes  its  first  character.
  381.      Conversely,  C uses a zero-byte to mark the end of its strings,  which
  382.      means  that extra steps (and time) will be needed to  determine  their
  383.      length  before  beginning  the search.   SearchString  could  also  be
  384.      modified  to accept additional parameters for the string lengths  when
  385.      called  from  C to save that added overhead.  Indeed, BASIC's  use  of
  386.      string  descriptors  is one of the primary reasons it is  so  fast  at
  387.      string operations.
  388.      
  389.           I believe it is important to point out how fast and well-designed
  390.      BASIC  really  is.   Many programmers unfairly criticize  BASIC  as  a
  391.      language,  solely  because  of the interpreter that  comes  with  DOS.
  392.      Besides  being extremely easy to use, current versions  of  QuickBASIC
  393.      offer a wealth of structured programming features, while offering more
  394.      commands  and features than any other high-level language.  And as  we
  395.      have seen, QuickBASIC is also aptly named.
  396.      
  397.      Ethan  Winer  is  President  of Cresent Software  and  the  author  of
  398.      QuickPak and PDQ.
  399.      
  400.      [EDITORS NOTE]
  401.           The source code to String Search is in the archive SSEARCH.ZIP.
  402.      
  403.  
  404.  
  405.  
  406.      The QBNews                                                     Page  5
  407.      Volume  1, Number  2                                 February  2, 1990
  408.  
  409.      The Speedy INSTR Function - Programming a Backwards INSTR Routine
  410.      by  Larry Stone
  411.      
  412.           One  of  the easiest traps to fall into is using  the  FOR...NEXT
  413.      loop to search a string for a sub-string.  I call it a trap because it
  414.      seems the obvious choice of functions to use, when, often-time, it  is
  415.      neither the fastest, nor the best of available choices.
  416.      
  417.           The choice of the FOR...NEXT loop seems the obvious because  when
  418.      we  use it, we do so on a variable who's length is known.  So why  not
  419.      just  step through it, character by character, and look for  the  sub-
  420.      string?
  421.      
  422.           The  drawback in using the FOR...NEXT loop is, primarily,  speed.
  423.      A  typical use (as demonstrated by the correspondence in the  Quik_BAS
  424.      echo) is finding the starting point of a sub-string, i.e., looking for
  425.      a  file name embedded within a complete path and  filename  statement.
  426.      Now, let's look what happens when you use a FOR...NEXT loop:
  427.      
  428.           fullName$ = "C:\UTILITY\DISK\PCTOOLS\PCTOOLS.EXE"
  429.           length% = LEN(fullName$)
  430.           FOR A% = 1 TO length%
  431.                IF MID$(fullName$, A%, 1) = "\" THEN B% = A%
  432.           NEXT
  433.      
  434.           In the above example, we are looking for a sub-string composed of
  435.      only  one backslash character.  The string to search is 35  characters
  436.      long.   This  means  we  must loop 35 times  in  order  to  find  four
  437.      occurrences of the sub-string.  Pretty inefficient, isn't it?  All  we
  438.      wanted  was the last occurrence of the backslash character and we  had
  439.      to  loop  35 times only to discover that the last  occurrence  was  at
  440.      position 24 (In the above example, B% will equal 24).
  441.      
  442.           The  INSTR  function handles the above solution in  a  much  more
  443.      elegant  manner.   The  example below is a  backwards  INSTR  routine.
  444.      Although it does not, in actuality, step negatively through a  string,
  445.      it quickly reports the last occurrence of any sub-string.
  446.      
  447.           fullName$ = "C:\UTILITY\DISK\PCTOOLS\PCTOOLS.EXE"
  448.           searchString$  =  fullName$
  449.           subString$  = "\"
  450.           P%  =  BackInstr%(0, searchString$, subString$)
  451.           PRINT "The last position of the backslash is"; P%
  452.      
  453.           FUNCTION BackInstr% (start%, searchString$, subString$)
  454.                IF start% = 0 THEN start% = 1
  455.                N% = INSTR(start%, searchString$, subString$)
  456.                A% = N%
  457.                DO WHILE N%
  458.                     N% = N% + 1
  459.                     N% = INSTR(N%, searchString$, subString$)
  460.                     IF N% THEN A% = N%
  461.                LOOP
  462.                BackInstr% = A%
  463.           END FUNCTION
  464.      
  465.      The QBNews                                                     Page  6
  466.      Volume  1, Number  2                                 February  2, 1990
  467.  
  468.      
  469.      
  470.           The  elegance  of this function is that your  DO...LOOP  executes
  471.      exactly four times - once for each occurrence of the backslash!  Speed
  472.      of execution is achieved because there is only four iterations of  the
  473.      loop instead of the 35 in the FOR...NEXT loop, and speed of  execution
  474.      is  further  improved because of the way the  BASIC's  INSTR  function
  475.      works.
  476.      
  477.           The  INSTR  function  does not  do  a  "brute-force"  evaluation,
  478.      comparing  every character in both strings.  Instead, it isolates  the
  479.      first character and then looks for the first occurrence of a  possible
  480.      match.   Looking for a single character is much faster  than  checking
  481.      every  character.   If a match is found, and if  subString$  had  more
  482.      characters  in it, then the next character is searched.  If  the  next
  483.      character is not matched, INSTR proceeds from the next position in the
  484.      string  where  the  first match was found, requiring  that  much  less
  485.      string  to  search.  The actual asm instruction used is  scasb.   This
  486.      technique is twice as fast as the Boyer-Moore algorithm, considered by
  487.      many  as a bench-mark.  For a more exact description of  the  process,
  488.      read   an   article  called,  "QuickBASIC's  Fast   String   Searching
  489.      Algorithm", in the Programmer's Journal, 7.6, authored by Ethan  Winer
  490.      of Crescent Software.(See Above)
  491.      
  492.           Would you like your programs, when they search for a  sub-string,
  493.      to search for exact matches as well as, embedded matches?  Simply swap
  494.      the  locations  of the search string and the sub-string.   Here's  how
  495.      INSTR can work for you:
  496.      
  497.           searchString$ = "These"
  498.           subString$ = "The"
  499.           start% = 1
  500.      
  501.           '---- Check one string against the other.
  502.      
  503.           N% = INSTR(start%, searchString$, subString$)
  504.           IF N% THEN
  505.      
  506.           '---- If a match was found, swap locations and search again.
  507.      
  508.                N% = INSTR(subString$, searchString$)
  509.                IF N% THEN
  510.      
  511.           '---- Now, if a match was found then it's an exact match.
  512.      
  513.                     PRINT "Sub-String is Exact Match of Search String"
  514.                ELSE
  515.      
  516.           '---- Otherwise, it's an embedded match.
  517.      
  518.                     PRINT "Sub-String is Embedded in Search String"
  519.                END IF
  520.           ELSE
  521.      
  522.           '---- The sub-string was not located in the Search String.
  523.      
  524.      The QBNews                                                     Page  7
  525.      Volume  1, Number  2                                 February  2, 1990
  526.  
  527.      
  528.                PRINT "Sub-String is Not Found in Search String"
  529.           END IF
  530.      
  531.      
  532.           The  example  above will report that N% is equal to  one  because
  533.      "The"  is  a subset of "These".  To have this code  determine  whether
  534.      "The"  and  "These"  are exact matches  would  require  the  BackInstr
  535.      function.  Use it to find the end of the word that was matched (use  a
  536.      space,  period, and hyphen as sub-strings).  When you know  where  the
  537.      end of the word is, simply state that: word$ = MID$(searchString$, N%,
  538.      P%).   Then,  use  the INSTR  function  to  compare  INSTR(subString$,
  539.      word$).
  540.      
  541.           If  you  wish  to move through the  searchString$  for  the  next
  542.      occurrence  of  a match, place all but the first three lines  of  code
  543.      within a DO WHILE start%...LOOP.  If N% is some positive value,  then,
  544.      at  the bottom of the loop, LET start% = N% + 1.  Otherwise, if N%  is
  545.      zero,  then LET start% = N% to end the loop.  When you  are  searching
  546.      for more than one occurrence of a match, you should have an escape key
  547.      assigned  to  get you out of the loop. A$ = INKEY$: IF A$  =  CHR$(27)
  548.      THEN EXIT DO works quite well.
  549.      
  550.           One word of caution.  The INSTR function returns zero whenever  a
  551.      compiled .EXE uses the literals CHR$(1) or CHR$(2) in a string.   This
  552.      should not, however, cause any problems in QB's environment.
  553.      
  554.  
  555.  
  556.  
  557.  
  558.  
  559.  
  560.  
  561.  
  562.  
  563.  
  564.  
  565.  
  566.  
  567.  
  568.  
  569.  
  570.  
  571.  
  572.  
  573.  
  574.  
  575.  
  576.  
  577.  
  578.  
  579.  
  580.  
  581.  
  582.      The QBNews                                                     Page  8
  583.      Volume  1, Number  2                                 February  2, 1990
  584.  
  585.  
  586.  
  587.      ----------------------------------------------------------------------
  588.         W h o   y a   g o n n a   c a l l ?   C A L L   I N T E R R U P T
  589.      ----------------------------------------------------------------------
  590.  
  591.      Using the PSP by Hector Plasmic
  592.      
  593.      
  594.           COMMAND$  lets you see what was entered on the command line  (the
  595.      command  tail)  by  the  user when  your  program  was  started.   For
  596.      instance, if the user typed:
  597.      
  598.      C:\> PROGRAM -a -b
  599.      
  600.           PRINT  COMMAND$ would display "-A -B".  Notice that  the  command
  601.      tail was uppercased by COMMAND$, though.  What if you need to  receive
  602.      case sensitive information from the command line?
  603.      
  604.           Well,  it just happens that DOS can provide you with the  answer.
  605.      DOS  keeps  an  area called the PSP  (program  segment  prefix)  which
  606.      contains  a  lot of potentially useful information  in  the  following
  607.      format:
  608.      
  609.      0000h   Interrupt 20h
  610.      0002h   Segment, end of allocation block
  611.      0004h   Reserved
  612.      0005h   Long call to MS-DOS function handler
  613.      000Ah   Previous contents of termination handler interrupt vector
  614.              (Int 22h)
  615.      000Eh   Previous contents of CTRL-C interrupt vector (Int 23h)
  616.      0012h   Previous contents of critical-error interrupt vector (Int 24h)
  617.      0016h   Reserved
  618.      002Ch   Segment address of environment block
  619.      002Eh   Reserved
  620.      005Ch   Default file control block #1
  621.      006Ch   Default file control block #2 (overlaid if FCB #1 opened)
  622.      0080h   Command tail and default DTA (buffer)
  623.      
  624.           So, to get the command tail in its pre-uppercased format, all  we
  625.      have to do is PEEK into the PSP.  But how do we find out where the PSP
  626.      is?  Interrupt  21h function 62h will get it for  you,  returning  the
  627.      PSP's segment in register .bx.  If DEF SEG is set to the returned  .bx
  628.      value, PEEK will be looking at the PSP.
  629.      
  630.           What follows is a simple program to get the command tail from the
  631.      PSP, list the environment, and return the name of the program that's
  632.      currently running.
  633.      
  634.      
  635.      DEFINT A-Z
  636.      
  637.       TYPE RegType
  638.            AX    AS INTEGER
  639.            BX    AS INTEGER
  640.            CX    AS INTEGER
  641.            DX    AS INTEGER
  642.      
  643.      The QBNews                                                     Page  9
  644.      Volume  1, Number  2                                 February  2, 1990
  645.  
  646.            BP    AS INTEGER
  647.            SI    AS INTEGER
  648.            DI    AS INTEGER
  649.            Flags AS INTEGER
  650.       END TYPE
  651.      
  652.       TYPE RegType2
  653.            AX    AS INTEGER
  654.            BX    AS INTEGER
  655.            CX    AS INTEGER
  656.            DX    AS INTEGER
  657.            BP    AS INTEGER
  658.            SI    AS INTEGER
  659.            DI    AS INTEGER
  660.            Flags AS INTEGER
  661.            DS AS INTEGER
  662.            ES AS INTEGER
  663.       END TYPE
  664.      
  665.      'You must link in QB.LIB (QB.QLB) for Interrupt
  666.      
  667.      DECLARE SUB Interrupt (Intnum%, InReg AS RegType, OutReg AS RegType)
  668.      DECLARE  SUB  InterruptX  (Intnum%, InReg2  AS  RegType2,  OutReg2  AS
  669.      RegType2)
  670.      
  671.      DIM SHARED InReg AS RegType
  672.      DIM SHARED OutReg AS RegType
  673.      
  674.      InReg.AX = 25088      'Find PSP
  675.      Interrupt &H21, InReg, OutReg
  676.      
  677.      DEF SEG = OutReg.BX   'Segment of PSP
  678.      
  679.      EnvLo = PEEK(&H2C)    'The pointers from the PSP to our copy of the
  680.      EnvHi = PEEK(&H2D)    'environment
  681.      
  682.      ComlineLength = PEEK(&H80)  'Length of command tail in PSP
  683.      
  684.      CLS
  685.      PRINT "  Command tail:": PRINT
  686.      
  687.      'Print command tail
  688.      
  689.      FOR X = &H81 TO &H81 + ComlineLength - 1
  690.        PRINT CHR$(PEEK(X));
  691.      NEXT
  692.      
  693.      PRINT : PRINT
  694.      
  695.      DEF SEG = EnvLo + (EnvHi * 256) 'Segment of environment
  696.      
  697.      X = 0
  698.      
  699.      'Print environment
  700.      
  701.      
  702.      The QBNews                                                     Page 10
  703.      Volume  1, Number  2                                 February  2, 1990
  704.  
  705.      PRINT "  Environment:": PRINT
  706.      
  707.      DO UNTIL PEEK(X) = 0
  708.          DO UNTIL PEEK(X) = 0
  709.              PRINT CHR$(PEEK(X));
  710.              X = X + 1
  711.          LOOP
  712.          PRINT
  713.          X = X + 1
  714.      LOOP
  715.      PRINT
  716.      
  717.      X = X + 3
  718.      
  719.      PRINT "  Program drive:\path\name:": PRINT
  720.      
  721.      'Print program filespec
  722.      
  723.      DO UNTIL PEEK(X) = 0
  724.          PRINT CHR$(PEEK(X));
  725.          X = X + 1
  726.      LOOP
  727.      
  728.      PRINT
  729.      
  730.      END
  731.      
  732.      
  733.           Knowing where the PSP is gives you yet another advantage.  When a
  734.      QuickBASIC  program RUNs another program outside the environment,  the
  735.      RUN  program inherits the old PSP, _including_ the old  command  tail.
  736.      If we change that command tail before RUNning the new program, we  can
  737.      pass  arguments  to  it as if they were typed  on  the  command  line!
  738.      Here's the Sub to do it:
  739.      
  740.      
  741.      '
  742.      SUB RunIt (Tail$, Prog$)        'Changes command tail and RUN program
  743.      
  744.      InReg.AX = 25088                'Find PSP
  745.      Interrupt &H21, InReg, OutReg
  746.      
  747.      DEF SEG = OutReg.BX             'Point PEEK and POKE at it
  748.      
  749.      Text$ = Text$ + " " + CHR$(13)  'Prep the new command tail
  750.      POKE &H80, LEN(Text$) - 1       'Poke the length
  751.      
  752.      FOR X = &H81 TO &H81 + LEN(Text$)  'Poke the string
  753.        POKE X, ASC(MID$(Text$, X - &H80, 1) + " ")
  754.      NEXT
  755.      
  756.      RUN Prog$                       'Run the program (.EXE or .COM)
  757.      
  758.      END SUB
  759.      
  760.      
  761.      The QBNews                                                     Page 11
  762.      Volume  1, Number  2                                 February  2, 1990
  763.  
  764.      
  765.      To  test this Sub, use it to RUN a program that just PRINTs  COMMAND$,
  766.      and see if it picks up your new command tail.
  767.      
  768.  
  769.  
  770.  
  771.  
  772.  
  773.  
  774.  
  775.  
  776.  
  777.  
  778.  
  779.  
  780.  
  781.  
  782.  
  783.  
  784.  
  785.  
  786.  
  787.  
  788.  
  789.  
  790.  
  791.  
  792.  
  793.  
  794.  
  795.  
  796.  
  797.  
  798.  
  799.  
  800.  
  801.  
  802.  
  803.  
  804.  
  805.  
  806.  
  807.  
  808.  
  809.  
  810.  
  811.  
  812.  
  813.  
  814.  
  815.  
  816.  
  817.  
  818.  
  819.      The QBNews                                                     Page 12
  820.      Volume  1, Number  2                                 February  2, 1990
  821.  
  822.  
  823.  
  824.      ----------------------------------------------------------------------
  825.                     P r o d u c t   A n n o u n c e m e n t s
  826.      ----------------------------------------------------------------------
  827.  
  828.      Microsoft Professional BASIC 7.0
  829.      REDMOND, Wash. -- November 27, 1989 --
  830.      
  831.      Microsoft   Corporation   today   announced  the   MicrosoftR   BASIC
  832.      Professional Development System, the  first BASIC product designed to
  833.      offer  serious  BASIC  programmers the  tools they  need  to  develop
  834.      powerful  professional applications. The  product will  be  available
  835.      through Microsoft retail outlets in December.
  836.      
  837.      "This  product  represents a quantum leap for  BASIC,"  said  Charles
  838.      Stevens,  general manager of Microsoft's Data Access  Business  Unit.
  839.      "It addresses the needs our BASIC customers said were most important.
  840.      While  Microsoft QuickBASIC is still the right choice  for  beginning
  841.      and occasional programmers, the BASIC Professional Development System
  842.      is truly tailored for serious BASIC programming professionals."
  843.      
  844.      The Microsoft BASIC Professional Development System is the result  of
  845.      extensive  research that showed BASIC programmers have a strong  need
  846.      for  high-end  tools.  It includes the  Microsoft  Professional  ISAM
  847.      (Indexed  Sequential  Access Method) for data management  tasks;  new
  848.      language  features;  increased  memory  capacity  to  support   large
  849.      application  development; and an integrated  development  environment
  850.      based  on Microsoft QuickBASIC.  Executables generated with  the  new
  851.      BASIC product rival those of traditional "high-performance" languages
  852.      in both size and speed.
  853.      
  854.      New Features Expedite Business Programming
  855.      
  856.      Many  applications  written in BASIC are for business uses,  such  as
  857.      accounting and data management tasks.  To reduce the effort needed to
  858.      develop  these applications, Microsoft has added a  fully  integrated
  859.      ISAM  to  the  new BASIC product.  The  single-user  integrated  ISAM
  860.      provides file handling capabilities; but unlike in other ISAMs,  such
  861.      as  NovellR  BTrieveR,  the powerful and elegant  command  syntax  is
  862.      integrated directly into the BASIC language.
  863.      
  864.      The  Microsoft BASIC Professional Development System also includes  a
  865.      new  fixed-decimal-point data type for representing  currencies;  and
  866.      three  add-on  libraries, derived from Microsoft Excel,  for  numeric
  867.      formatting, date/time and financial functions.
  868.      
  869.      Microsoft Answers User Requests with New Language Features  Microsoft
  870.      added several features requested by BASIC programmers.  Static arrays
  871.      in  records  allow creation of more  sophisticated  data  structures.
  872.      Errors  can now be trapped and handled locally in a subprogram.   DOS
  873.      file control statements make it easy to write programs to  manipulate
  874.      the DOS file system.
  875.      
  876.      Increased Memory Capacity Removes Limitations
  877.      
  878.      The  Microsoft  BASIC  Professional Development  System  has  removed
  879.      
  880.      The QBNews                                                     Page 13
  881.      Volume  1, Number  2                                 February  2, 1990
  882.  
  883.      barriers  limiting  the size of BASIC programs. To  accomplish  this,
  884.      Microsoft  added  EMS  (Expanded Memory  Specification)  support  and
  885.      increased   total  string  space  in  the  development   environment.
  886.      Compiled  executables  can also take advantage of more  total  string
  887.      space, as well as overlays, to create programs as large as 16 MB.
  888.      
  889.      Smaller, Faster Executables Rival Other Languages
  890.      
  891.      BASIC  programmers  told Microsoft that their top priorities  were  a
  892.      reduction  in  .EXE  size and an increase  in  speed.   With  special
  893.      enhancements in code generation, run- time performance and 80286 code
  894.      generation, BASIC now matches the features and performance offered by
  895.      other professional languages.  Developers have increased control over
  896.      the size and content of the BASIC run-time, thus reducing  executable
  897.      program size.
  898.      
  899.      Microsoft    QuickBASIC    Extended    Environment,    Other    Tools
  900.      BoostProductivity
  901.      
  902.      The new product includes a high-performance development  environment,
  903.      sample-code  toolboxes,  and tools for mixed- language and  MSR  OS/2
  904.      system  programming.   Professional programmers will  appreciate  the
  905.      increased capacities and added features of the integrated development
  906.      environment,  which  is  extended  from  Microsoft  QuickBASIC.   The
  907.      sample-code  toolboxes  --  including  user-interface,   presentation
  908.      graphics   and  matrix  math  routines  --  illustrate   how   common
  909.      programming  problems  can be solved with  generalized  and  reusable
  910.      BASIC  code.  The Microsoft CodeViewR debugger and  Microsoft  Editor
  911.      are included for mixed-language and OS/2 systems programming.
  912.      
  913.      System Requirements, Pricing and Availability
  914.      
  915.      The  Microsoft  BASIC  Professional  Development  System  requires  a
  916.      personal computer running MS-DOSR or PC-DOSTM operating system 3.0 or
  917.      OS/2 operating system 1.1 or higher; one double-sided disk drive  and
  918.      a  hard  disk;  and  a  minimum  of  640K  of  memory  (EMS  4.0   is
  919.      recommended).  A Microsoft Mouse is optional.  Compiled programs  run
  920.      on MS-DOS 2.1 or higher or OS/2 operating system 1.1 or higher.
  921.      
  922.           The  Microsoft  BASIC Professional Development  System  will  be
  923.      available  in  December 1989 at Microsoft retail outlets.  It  has  a
  924.      suggested  retail  price of $495.  The upgrade price  for  registered
  925.      users of Microsoft Basic 6.0 is $150.
  926.                                    #########
  927.      
  928.      Microsoft  BASIC Professional Development System Microsoft,  MS,  MS-
  929.      DOS,  CodeView  and the Microsoft logo are registered  trademarks  of
  930.      Microsoft Corporation.
  931.      Btrieve  is  a  registered  trademark of  Software,  Inc.,  a  Novell
  932.      Company.
  933.      Novell is a registered trademark of Novell, Inc.
  934.      PC-DOS is a trademark of International Business Machines Corporation.
  935.      
  936.  
  937.  
  938.      The QBNews                                                     Page 14
  939.      Volume  1, Number  2                                 February  2, 1990
  940.  
  941.      QUICKBASIC B+ TREE FILE INDEXING
  942.      
  943.      For years there has been a crying need for an easy to use, reasonably
  944.      priced  file  indexing system for QuickBASIC.  This problem  has  now
  945.      been  solved with Index Manager(tm).  Programmers can now  create  B+
  946.      tree  file  indexes within their QuickBASIC programs.  Files  can  be
  947.      accessed  randomly  by full key, browsed by partial  key,  or  sorted
  948.      forward or backward.  All functions of Index Manager are performed by
  949.      just one external subroutine, making Index Manager very easy to  use.
  950.      Only indexes are managed.  The programmer still retains full  control
  951.      over all data files.
  952.      
  953.      Index Manager creates its indexes using a prefix B+ tree - one of the
  954.      most  powerful  index  structures available today.   The  program  is
  955.      written in assembler language for maximum speed and minimum size.  It
  956.      utilizes  a  large  cache buffer to keep  the  most  important  index
  957.      records  in memory and thereby reduce disk access to a minimum.   The
  958.      result is a very fast, exceptionally powerful indexing system.
  959.      
  960.      Two-thirds of the Beta Testers for Index Managers gave it an  overall
  961.      rating  of  10 out of 10.  ProWindows author David  Stasinski  called
  962.      Index Manager "the absolute best B-tree system I have ever seen."
  963.      
  964.      A  demo  version  of Index Manager is available  for  downloading  on
  965.      Compuserve  and GEnie.  On Compuserve it is located on the  Microsoft
  966.      System  Forum  (GO  MSSYS)  on  data  library  1  or  2,  and  called
  967.      INDEXM.ARC.  On GEnie, it is located in Microsoft (M 505)  RoundTable
  968.      data library 10 as file 828.
  969.      
  970.      The  Index Manager package includes a high quality perfect  bound  64
  971.      page  Users  Guide, 8 sample programs, and a  Quick  Reference  card.
  972.      Index Manager can be purchased for $59 from
  973.      
  974.              CDP Consultants
  975.              1700 Circo Del Cielo Drive
  976.              El Cajon, CA 92020
  977.      
  978.              or by phone at 619-440-6482.
  979.      
  980.  
  981.  
  982.  
  983.  
  984.  
  985.  
  986.  
  987.  
  988.  
  989.  
  990.  
  991.  
  992.  
  993.  
  994.  
  995.  
  996.      The QBNews                                                     Page 15
  997.      Volume  1, Number  2                                 February  2, 1990
  998.  
  999.                                 QB/Pro Volume 8
  1000.      
  1001.                          The MicroHelp Library Manager
  1002.      
  1003.                                A Simple Concept
  1004.      We've  revolutionized the way that programmers think about  libraries.
  1005.      Instead  of worrying about what object modules go in  what  libraries,
  1006.      our  Library  Manager  (LM.EXE) lets you  organize  your  routines  by
  1007.      project.
  1008.      
  1009.      Whenever  you  want  to build a fresh library, whether  it's  a  Quick
  1010.      Library,  a LINK Library, or an Extended Runtime Library, simply  tell
  1011.      LM  the Project(s) that you want the library for and then tell  it  to
  1012.      build the library!
  1013.      
  1014.                           View Library Contents
  1015.      LM  lets you view the contents of both Quick and LINK  libraries.   In
  1016.      fact,  the  program lets you modify LINK libraries without  having  to
  1017.      worry about command line switches. Simply mark the action you want  to
  1018.      take on each module in the library.
  1019.      
  1020.                     Easy-To-Use Search Capabilities
  1021.      You  can configure LM so that it automatically searches your disk  for
  1022.      "unresolved externals". That means you don't have to worry about where
  1023.      a routine is located - all you need is the routine name! LM can search
  1024.      object  modules  and LINK libraries in order to resolve  all  external
  1025.      references.
  1026.      
  1027.      As  a matter of fact, LM even lets you look inside object modules,  so
  1028.      you  can tell what routines are included. If you see one you  want  to
  1029.      use, simply tell LM to add it to your standard list of routines.
  1030.      
  1031.      When  you're viewing a LINK library or set of object modules, you  can
  1032.      tell LM to search for specified public symbols or externals.
  1033.      
  1034.      
  1035.                             The Nitty Gritty
  1036.      LM is designed to work with two main types of information:
  1037.      
  1038.           Standard  Routines that you use on a regular basis.  The  product
  1039.      comes with a text file containing the names of all the routines in all
  1040.      of  MicroHelp's  products. You can add your own routines, as  well  as
  1041.      routines  from  other add-on  products, and delete  the  routines  you
  1042.      don't normally use.
  1043.      
  1044.           Standard  Projects  tell LM how you want to group  your  Standard
  1045.      Routines. You can load up to 250 different projects at one time,  each
  1046.      having  a  unique  code  and a  description.  After  designating  your
  1047.      projects, you can go through your standard routines and tell LM  which
  1048.      routines  are  to be included with each product. We even  give  you  a
  1049.      "wildcard  project"  that  tells  LM  to  include  a  routine  in  all
  1050.      libraries.
  1051.      
  1052.      You  can add to your list of Standard Routines automatically  whenever
  1053.      you View a LINK library or View Object Modules. When you want to build
  1054.      
  1055.      The QBNews                                                     Page 16
  1056.      Volume  1, Number  2                                 February  2, 1990
  1057.  
  1058.      a library, you simply select one or more Projects and then tell LM  to
  1059.      go  to work. If you prefer, you can tell LM to use the  routines  that
  1060.      you specify instead of or in addition to the Project(s) you  selected.
  1061.      This allows you to build custom libraries without having to specify  a
  1062.      new Project.
  1063.      
  1064.      
  1065.                          For Your Convenience
  1066.      LM  is very flexible with its configuration. Not only does  it  search
  1067.      for  its configuration file using the same logic described  above,  it
  1068.      also lets you configure the default path for:
  1069.      
  1070.             Quick Libraries
  1071.             LINK Libraries
  1072.             Standard Routine and Standard Project files
  1073.             Temporary work files
  1074.             Object modules
  1075.      
  1076.      You can also configure the following to suit your preferences:
  1077.      
  1078.             Quick Library Support Library
  1079.             Default LINK library name
  1080.             Default Quick library name
  1081.             Whether or not to resolve external references when
  1082.             building a library.
  1083.             Whether or not to search libraries in order to resolve the
  1084.             externals.
  1085.             Whether or not object module presence should be verified
  1086.             before invoking LINK or LIB.
  1087.      
  1088.      
  1089.                          Free Utility Program Included
  1090.      Included with The MicroHelp Library Manager is a FREE Utility  program
  1091.      called  PREQLB.  When  you absolutely positively have to  have  a  new
  1092.      library  for  a program right now, just tell PREQLB the name  of  your
  1093.      source  file.  PREQLB  will  quickly  scan  your  program,   including
  1094.      supporting BASIC modules, and will help you create a new Quick Library
  1095.      or LINK Library immediately.
  1096.      
  1097.      PREQLB also tells you if you have DECLAREd a SUBprogram, but it is not
  1098.      used in your program, or if you have a SUB or FUNCTION in your program
  1099.      that is not invoked by the program.
  1100.      
  1101.      
  1102.                             System Requirements
  1103.      The minimum system requirements for using The MicroHelp Library
  1104.      Manager are:
  1105.      
  1106.             An IBM PC, XT, AT, PS/2 or close compatible.
  1107.             PC/MS DOS version 3.00 or later.
  1108.             LIB.EXE (any version) and LIB.EXE 3.61 or later.
  1109.             Any Microsoft or IBM BASIC compiler. Quick Libraries
  1110.             require Microsoft QuickBASIC 4.0 or later or Microsoft
  1111.             BASIC Compiler 6.0 or later, as well as the LINK program
  1112.             that comes with the compiler.
  1113.      
  1114.      The QBNews                                                     Page 17
  1115.      Volume  1, Number  2                                 February  2, 1990
  1116.  
  1117.             A hard disk (fixed disk).
  1118.             1 Diskette drive (5.25"). 3.5" disks are available for a
  1119.             nominal charge.
  1120.             An 80 column monitor.
  1121.      
  1122.      
  1123.                                 The Last Word
  1124.      
  1125.      The MicroHelp Library Manager comes with a three-ring bound manual and
  1126.      free full-time technical support. The suggested retail price is $59.00.
  1127.      
  1128.      To order, or for more information, contact:
  1129.      
  1130.               MicroHelp, Inc.
  1131.               4636 Huntridge Drive
  1132.               Roswell, GA 30075-2012
  1133.               (800) 922-3383
  1134.               (404) 552-0565
  1135.      
  1136.  
  1137.  
  1138.  
  1139.  
  1140.  
  1141.  
  1142.  
  1143.  
  1144.  
  1145.  
  1146.  
  1147.  
  1148.  
  1149.  
  1150.  
  1151.  
  1152.  
  1153.  
  1154.  
  1155.  
  1156.  
  1157.  
  1158.  
  1159.  
  1160.  
  1161.  
  1162.  
  1163.  
  1164.  
  1165.  
  1166.  
  1167.  
  1168.  
  1169.  
  1170.  
  1171.  
  1172.      The QBNews                                                     Page 18
  1173.      Volume  1, Number  2                                 February  2, 1990
  1174.  
  1175.  
  1176.  
  1177.      ----------------------------------------------------------------------
  1178.                             T h e   T o o l   S h e d
  1179.      ----------------------------------------------------------------------
  1180.  
  1181.      Update on QB Optimizer by Larry Stone
  1182.      
  1183.           When  "The  QBNews" last went to press, I was still  awaiting  QB
  1184.      4.0b  from  Microsoft.  Without this upgrade, it was not  possible  to
  1185.      give a more extensive review of MicroHelp's QB Optimizer.
  1186.      
  1187.           Well, the update from Microsoft finally arrived and I immediately
  1188.      re-compiled  my test program, FULLCUR.BAS, using all of  the  Xmodules
  1189.      supplied by MicroHelp.  The stand-alone exe compiled to 3343 bytes, as
  1190.      I anticipated.
  1191.      
  1192.           Because  I  now  have the opportunity  to  thoroughly  test  Mark
  1193.      Novisoff's utility, I will post my findings in future editions of this
  1194.      electronic newsletter.
  1195.      
  1196.      
  1197.      [EDITORS NOTE]
  1198.      
  1199.           Because  of my procrastination, there are no new reviews in  this
  1200.      issue. In the next issue, (April), look for reviews on Index  Manager,
  1201.      P-Screen Professional, and Stay-Res Plus.
  1202.      
  1203.      David Cleary
  1204.      
  1205.  
  1206.  
  1207.  
  1208.  
  1209.  
  1210.  
  1211.  
  1212.  
  1213.  
  1214.  
  1215.  
  1216.  
  1217.  
  1218.  
  1219.  
  1220.  
  1221.  
  1222.  
  1223.  
  1224.  
  1225.  
  1226.  
  1227.  
  1228.  
  1229.  
  1230.  
  1231.  
  1232.      The QBNews                                                     Page 19
  1233.      Volume  1, Number  2                                 February  2, 1990
  1234.  
  1235.  
  1236.  
  1237.      ----------------------------------------------------------------------
  1238.                           A s k   M R .   W I Z Z A R D
  1239.      ----------------------------------------------------------------------
  1240.  
  1241.      Ask Mr. Wizard    Information from the Microsoft Knowledge Base
  1242.      
  1243.           The   Microsoft  Knowledge  Base  is  a  service  available   to
  1244.      subscribers  on  Compuserve.  It is a database  of  frequently  asked
  1245.      questions  that  Microsoft  Tech  Support uses  to  find  answers  to
  1246.      questions  asked  to them. The QBNews has been  given  permission  to
  1247.      reprint  some of these answers. You can access the Knowledge Base  on
  1248.      Compuserve by typing GO MSOFT at any ! prompt.
  1249.      
  1250.      Question:  Gee Mr. Wizard, What do the "Bytes Available"  and  "Bytes
  1251.      Free" mean when I compile?
  1252.      
  1253.      Well Tudor . . .
  1254.      
  1255.      Title: Explanation of Compiler "Bytes Available" and "Bytes Free"
  1256.      Document Number: Q27347           Publ Date: 16-JAN-1989
  1257.      Product Name: Microsoft QuickBASIC Compiler
  1258.      Product Version:  4.00 4.00 4.50
  1259.      Operating System: MS-DOS
  1260.      
  1261.      Summary:
  1262.      
  1263.      At the end of a successful compilation, the BC.EXE compiler  displays
  1264.      the following message:
  1265.      
  1266.                      nnnnn Bytes Available
  1267.                      nnnnn Bytes Free
  1268.      
  1269.                              0 Warning Error(s)
  1270.                              0 Severe Error(s)
  1271.      
  1272.      This  message gives the amount of workspace available  before  (Bytes
  1273.      Available) and after (Bytes Free) a program is compiled.
  1274.      
  1275.      If  the  Bytes  Free  is  approaching 1024  or  less,  then  you  are
  1276.      approaching  the limits of code generation for this module,  and  you
  1277.      should   break  your  program  into  smaller,   separately   compiled
  1278.      subprograms or FUNCTION procedures that can be linked together  (with
  1279.      LINK.EXE).
  1280.      
  1281.      This information applies to QuickBASIC Compiler Versions 1.00,  1.01,
  1282.      1.02,  2.00,  2.01,  3.00,  4.00, 4.00b, and  4.50  for  MS-DOS,  the
  1283.      Microsoft  BASIC  Compiler  Versions 5.35 and 5.36  for  MS-DOS,  and
  1284.      Versions 6.00 and 6.00b for MS OS/2 and MS-DOS.
  1285.      
  1286.      More Information:
  1287.      
  1288.      The  64K  memory  segmentation  architecture of  the  8086  chip  has
  1289.      influenced  design limitations of the BASIC Compiler so that  it  can
  1290.      only  generate  64K  or less for a program's code  segment.  The  64K
  1291.      temporary work space available for the compiler itself can also limit
  1292.      
  1293.      The QBNews                                                     Page 20
  1294.      Volume  1, Number  2                                 February  2, 1990
  1295.  
  1296.      code generation.
  1297.      
  1298.      Bytes Available is the initial amount of compiler workspace available
  1299.      for  storing  the  symbol table and the line number  table,  and  for
  1300.      working storage for code generation and optimization.
  1301.      
  1302.      Bytes  Free  is  the  size of unused  compiler  workspace  after  the
  1303.      compiler has finished.
  1304.      
  1305.      Note: If you want to see the number of bytes that were generated  for
  1306.      a  module's  code  segment,  refer  to the  .MAP  file  that  can  be
  1307.      optionally  output  from the LINK.EXE linker. The program  must  have
  1308.      been successfully compiled and linked to get a valid link .MAP file.
  1309.      
  1310.      COPYRIGHT Microsoft Corporation, 1989.
  1311.      
  1312.  
  1313.  
  1314.  
  1315.  
  1316.  
  1317.  
  1318.  
  1319.  
  1320.  
  1321.  
  1322.  
  1323.  
  1324.  
  1325.  
  1326.  
  1327.  
  1328.  
  1329.  
  1330.  
  1331.  
  1332.  
  1333.  
  1334.  
  1335.  
  1336.  
  1337.  
  1338.  
  1339.  
  1340.  
  1341.  
  1342.  
  1343.  
  1344.  
  1345.  
  1346.  
  1347.  
  1348.  
  1349.  
  1350.  
  1351.      The QBNews                                                     Page 21
  1352.      Volume  1, Number  2                                 February  2, 1990
  1353.  
  1354.  
  1355.  
  1356.      ----------------------------------------------------------------------
  1357.                      G r a p h i c a l l y   S p e a k i n g
  1358.      ----------------------------------------------------------------------
  1359.  
  1360.      Getting and Putting Graphics by Frederick Volking
  1361.              
  1362.      Due  to  the Graphic nature of this article,  parental  discretion  is
  1363.      advised.
  1364.              
  1365.           I am involved in writing several graphics oriented games. Each of
  1366.      these  games  require many different images (called  sprites).  I  was
  1367.      evaluating  the best method to store these sprites for the  games  I'm
  1368.      writing.  I  noticed  the  graphics GET &  PUT  commands  could  store
  1369.      relatively large images in surprisingly small arrays.
  1370.      
  1371.           I decided that if I could understand the method used to store the
  1372.      images  in the arrays, then I could write a few routines  which  would
  1373.      make  my  games easier to program. Specifically routines  which  would
  1374.      manipulate  the  images ONCE THEY WERE ALREADY STORED  IN  THE  ARRAY!
  1375.      Routines  like; (1) "flipping" an image upside down or left to  right.
  1376.      (2)  rotating  an  image  around  a  fixed  point  (3)  changing   all
  1377.      occurrences of color-X to a new color-Y [easy way to make a "good guy"
  1378.      into a "bad guy"] ... and several other routines.
  1379.      
  1380.           I  thought  that if I could write small fast routines to  do  the
  1381.      above  actions,  then  I would need far fewer  sprites  to  accomplish
  1382.      the   same  visual  actions,  since  I  could  simply   "change"   the
  1383.      sprite, as needed, on-the-fly, while the program was running.
  1384.      
  1385.           The  below article is the result of many hours of  research  into
  1386.      the method used for storage of images into numeric arrays.
  1387.                 Enjoy ...
  1388.            ================================================> Frederick
  1389.      
  1390.           All  versions  of  Microsoft Basic have  several  commands  which
  1391.      provide  graphic functions. Two of the most powerful are the  graphics
  1392.      GET and graphics PUT. These two commands allow the programmer to  move
  1393.      a  copy  of a graphic image into a numerical array  and  then,  later,
  1394.      redisplay the image whenever needed anyplace on the screen.
  1395.      
  1396.           Almost  every  graphics game uses the technique  of  GET'ing  and
  1397.      PUT'ing  graphics images to create animation. During a game, when  our
  1398.      eye  sees  a  picture of an object moving across the  screen,  we  are
  1399.      actually seeing many separate images. Each image was initially  stored
  1400.      with a GET command. Then, throughout the game, the image is repeatedly
  1401.      redisplayed  with  subsequent PUT commands. The key  concept,  is  the
  1402.      speed  at  which this redisplay happens. The computer  is  capable  of
  1403.      PUT'ing,  so  rapidly, that the human eye cannot  see  the  individual
  1404.      different frames.
  1405.      
  1406.           The  GET and PUT commands use numerical arrays to  store  images.
  1407.      The method used for storage is the main concept to be examined by this
  1408.      article.
  1409.      
  1410.           In  Basic, only rectangularly shaped screen areas can  be  stored
  1411.      
  1412.      The QBNews                                                     Page 22
  1413.      Volume  1, Number  2                                 February  2, 1990
  1414.  
  1415.      and  displayed.  The  height and width dimensions of  such  areas  are
  1416.      determined  on a pixel basis. The height and width of a graphic  image
  1417.      is described as X-pixels-tall and Y-pixels-wide.
  1418.      
  1419.           GET  requires a numeric array which has been  pre-dimensioned  to
  1420.      the  proper size to receive the entire graphic image.  Depending  upon
  1421.      several  criteria, such as screen mode (CGA, EGA or VGA) or  how  many
  1422.      bytes  of graphics memory are available, the exact size and  dimension
  1423.      of  these arrays tend to vary significantly. It is this  variation  in
  1424.      array size, which provides the first clue to unraveling the complexity
  1425.      of image storage.
  1426.      
  1427.           In  Screen  Two  a  16x16 pixel image requires  an  array  of  18
  1428.      integers. However, 16x16 pixels in Screen One requires 34 integers and
  1429.      in  Screen Nine 66 integers are needed. It is immediately obvious  the
  1430.      screen mode being used has a great impact on the array size needed.
  1431.      
  1432.           In Screen Two (CGA Monochrome), the color of each pixel may  only
  1433.      be either white(ON) or black(OFF). In Screen One (CGA color) there are
  1434.      only  FOUR possible color choices and in Screen Nine, each pixel  must
  1435.      be one of SIXTEEN possible color choices.
  1436.      
  1437.           The  quantity  of colors available, under  any  specified  screen
  1438.      mode,  is the main factor affecting the size of the array required  to
  1439.      hold an image.
  1440.      
  1441.           Included  with  this article is a SUB which  will  calculate  the
  1442.      array size needed, in integers, for most screen modes. GETSIZE.BAS
  1443.      
  1444.           Numeric arrays dimensioned for image storage include two integers
  1445.      in  the first and second positions which are not part of the  graphics
  1446.      image  itself. The first and second integers are the height and  width
  1447.      of the image contained therein. These values are automatically set  by
  1448.      the GET command.
  1449.      
  1450.           Examination  of array sizes (minus the two extra integers) for  a
  1451.      variety of screen modes, for storage of a 16x16 pixel image, reveals a
  1452.      geometric pattern rise, in step with the quantity of colors available.
  1453.      
  1454.           SCREEN 2 .... 16 integers needed ...  2 colors available
  1455.           SCREEN 1 .... 32 integers needed ...  4 colors available
  1456.           SCREEN 9 .... 64 integers needed ... 16 colors available
  1457.      
  1458.           If  we examine the storage needs of a 16x16 pixel image  we  find
  1459.      there  are a total of 256 pixels to be stored. (16 pixels tall)  times
  1460.      (16 pixels wide) equals (256 pixels) to store.
  1461.      
  1462.           The  question  that must be answered is, "How do  you  store  256
  1463.      pixels in arrays which are only 16, 32 or 64 integers in size?
  1464.      
  1465.                             CGA - MONOCHROME SCREEN
  1466.      
  1467.           Let's  begin by concentrating on Screen Two where the entire  256
  1468.      pixels  are stored in only 16 integers and each pixel is either  Black
  1469.      or White ... ON or OFF ... 0(zero) or 1(one) ...
  1470.      
  1471.      The QBNews                                                     Page 23
  1472.      Volume  1, Number  2                                 February  2, 1990
  1473.  
  1474.      
  1475.                - One array of 16 INTEGERS
  1476.                - Each integer is composed of TWO BYTES
  1477.                - Each byte is made up of EIGHT BITS
  1478.                - Each bit is either a 0(zero) or 1(one) ...
  1479.      
  1480.           A  little  mathematics shows us we have (16  integers)  times  (2
  1481.      bytes) times (8 bits) which equals (256 bits).
  1482.      
  1483.      Since we have 256 PIXELS which are either 0(zero) or 1(one) ... and
  1484.      Since we have 256  BITS  which are either 0(zero) or 1(one) ...
  1485.      We can then THEORIZE that each pixel is "mapped" to the "bit-level".
  1486.      
  1487.      Included with this article is a program which will validate bit  level
  1488.      mapping in Screen Two: SCR2BITS.BAS
  1489.      
  1490.           To  prove  our  THEORY ... let's assume we have an  array  of  18
  1491.      integers  (two  for height and width and 16 for pixel  storage).  Each
  1492.      integer is composed of two bytes and each byte is composed of 8  bits.
  1493.      Set  every  integer in our array to 0(zero) and examine each  bit,  of
  1494.      each byte, of each integer:
  1495.      
  1496.                     Integer #1   0000 0000  0000 0000 = 0 (tall)
  1497.                     Integer #2   0000 0000  0000 0000 = 0 (wide)
  1498.                                   Byte #1    Byte #2
  1499.                     Integer #3   0000 0000  0000 0000
  1500.                     Integer #4   0000 0000  0000 0000
  1501.                     Integer #5   0000 0000  0000 0000
  1502.                     Integer #6   0000 0000  0000 0000
  1503.                     Integer #7   0000 0000  0000 0000
  1504.                     Integer #8   0000 0000  0000 0000
  1505.                     Integer #9   0000 0000  0000 0000
  1506.                     Integer #10  0000 0000  0000 0000
  1507.                     Integer #11  0000 0000  0000 0000
  1508.                     Integer #12  0000 0000  0000 0000
  1509.                     Integer #13  0000 0000  0000 0000
  1510.                     Integer #14  0000 0000  0000 0000
  1511.                     Integer #15  0000 0000  0000 0000
  1512.                     Integer #16  0000 0000  0000 0000
  1513.                     Integer #17  0000 0000  0000 0000
  1514.                     Integer #18  0000 0000  0000 0000
  1515.      
  1516.      Let's further ...
  1517.         1. turn on Screen 2                 > SCREEN 2
  1518.         2. draw a box in the corner         > LINE (0,0)-(15,15),1,B
  1519.         3. draw a diagonal line in the box  > LINE (0,0)-(15,15),1
  1520.         4. GET the image into our array     > GET (0,0)-(15,15),Array
  1521.      
  1522.      Now let's examine our array again ...
  1523.                     Integer #1   0001 0000  0000 0000 = 16 (tall)
  1524.                     Integer #2   0001 0000  0000 0000 = 16 (wide)
  1525.                                   Byte #1    Byte #2
  1526.                     Integer #3   1111 1111  1111 1111
  1527.                     Integer #4   1100 0000  0000 0001
  1528.                     Integer #5   1010 0000  0000 0001
  1529.      
  1530.      The QBNews                                                     Page 24
  1531.      Volume  1, Number  2                                 February  2, 1990
  1532.  
  1533.                     Integer #6   1001 0000  0000 0001
  1534.                     Integer #7   1000 1000  0000 0001
  1535.                     Integer #8   1000 0100  0000 0001
  1536.                     Integer #9   1000 0010  0000 0001
  1537.                     Integer #10  1000 0001  0000 0001
  1538.                     Integer #11  1000 0000  1000 0001
  1539.                     Integer #12  1000 0000  0100 0001
  1540.                     Integer #13  1000 0000  0010 0001
  1541.                     Integer #14  1000 0000  0001 0001
  1542.                     Integer #15  1000 0000  0000 1001
  1543.                     Integer #16  1000 0000  0000 0101
  1544.                     Integer #17  1000 0000  0000 0011
  1545.                     Integer #18  1111 1111  1111 1111
  1546.      
  1547.           We  have  proven  our theory. Examination  of  the  "bit-pattern"
  1548.      proves under Screen Two, each pixel is mapped at the bit level.  Given
  1549.      the  visual  pattern above, it's rather obvious how  Screen  Two  (CGA
  1550.      Mono) images are stored in the array.
  1551.      
  1552.                               CGA - COLOR SCREEN
  1553.      
  1554.           In  Screen Two (CGA Mono) it is only necessary to store a  single
  1555.      ON/OFF  switch  (one  bit). Thus, mapping to each  integer  is  rather
  1556.      straight forward. However, in Screen One (CGA color), it is  necessary
  1557.      to store a value which can be one of FOUR possible colors (0,1,2,3).
  1558.      
  1559.           Using  binary mathematics, we can determine it will only  require
  1560.      TWO BITS to store a value which has a range of 0 thru 3 ....
  1561.      
  1562.                       Bit#1 Bit#2                   Value
  1563.                        OFF   OFF  . . . . .  0  0  =  0
  1564.                        OFF    on  . . . . .  0  1  =  1
  1565.                         on   OFF  . . . . .  1  0  =  2
  1566.                         on    on  . . . . .  1  1  =  3
  1567.      
  1568.      We  must now determine how those two bits, for each pixel, are  mapped
  1569.      on the integer array.
  1570.      
  1571.      Included with this article is a program which will validate bit  level
  1572.      mapping in Screen One: SCR1BITS.BAS
  1573.      
  1574.           Let's examine an example ... Since we are now dealing with Screen
  1575.      One,  we  will need an array with 34 integers. Let's  set  the  entire
  1576.      array to 0(zero) and examine the "bit-pattern" of the array.
  1577.      
  1578.           Since  we need 2 bits to display each pixel, a single line of  16
  1579.      pixels  will now span 2 integers (rather than 1 integer as  in  Screen
  1580.      Two).  Thus we'll change the way our integers are displayed such  that
  1581.      we have two integers side by side
  1582.      
  1583.          Integer #1  0001 0000  0000 0000 = 16 (tall)
  1584.          Integer #2  0001 0000  0000 0000 = 16 (wide)
  1585.                   Byte #1    Byte #2       Byte #1    Byte #2
  1586.      Integer # 3 0000 0000  0000 0000  -  0000 0000  0000 0000 # 4 Integer
  1587.      Integer # 5 0000 0000  0000 0000  -  0000 0000  0000 0000 # 6 Integer
  1588.      
  1589.      The QBNews                                                     Page 25
  1590.      Volume  1, Number  2                                 February  2, 1990
  1591.  
  1592.      Integer # 7 0000 0000  0000 0000  -  0000 0000  0000 0000 # 8 Integer
  1593.      Integer # 9 0000 0000  0000 0000  -  0000 0000  0000 0000 #10 Integer
  1594.      Integer #11 0000 0000  0000 0000  -  0000 0000  0000 0000 #12 Integer
  1595.      Integer #13 0000 0000  0000 0000  -  0000 0000  0000 0000 #14 Integer
  1596.      Integer #15 0000 0000  0000 0000  -  0000 0000  0000 0000 #16 Integer
  1597.      Integer #17 0000 0000  0000 0000  -  0000 0000  0000 0000 #18 Integer
  1598.      Integer #19 0000 0000  0000 0000  -  0000 0000  0000 0000 #20 Integer
  1599.      Integer #21 0000 0000  0000 0000  -  0000 0000  0000 0000 #22 Integer
  1600.      Integer #23 0000 0000  0000 0000  -  0000 0000  0000 0000 #24 Integer
  1601.      Integer #25 0000 0000  0000 0000  -  0000 0000  0000 0000 #26 Integer
  1602.      Integer #27 0000 0000  0000 0000  -  0000 0000  0000 0000 #28 Integer
  1603.      Integer #29 0000 0000  0000 0000  -  0000 0000  0000 0000 #30 Integer
  1604.      Integer #31 0000 0000  0000 0000  -  0000 0000  0000 0000 #32 Integer
  1605.      Integer #33 0000 0000  0000 0000  -  0000 0000  0000 0000 #34 Integer
  1606.      
  1607.      Let's ...
  1608.         1. turn on Screen 1                     > SCREEN 1
  1609.         2. define the color to use              > Clr = 1
  1610.         3. draw a box in the corner             > LINE (0,0)-(15,15),Clr,B
  1611.         4. draw a diagonal line in the box      > LINE (0,0)-(15,15),Clr
  1612.         5. GET the image into our array         > GET (0,0)-(15,15),Array
  1613.      
  1614.      Now let's examine our array again ...
  1615.      
  1616.          Integer #1  0001 0000  0000 0000 = 16 (tall)
  1617.          Integer #2  0001 0000  0000 0000 = 16 (wide)
  1618.                   Byte #1    Byte #2       Byte #1    Byte #2
  1619.      Integer # 3 0101 0101  0101 0101  -  0101 0101  0101 0101 # 4 Integer
  1620.      Integer # 5 0101 0000  0000 0000  -  0000 0000  0000 0001 # 6 Integer
  1621.      Integer # 7 0100 0100  0000 0000  -  0000 0000  0000 0001 # 8 Integer
  1622.      Integer # 9 0100 0001  0000 0000  -  0000 0000  0000 0001 #10 Integer
  1623.      Integer #11 0100 0000  0100 0000  -  0000 0000  0000 0001 #12 Integer
  1624.      Integer #13 0100 0000  0001 0000  -  0000 0000  0000 0001 #14 Integer
  1625.      Integer #15 0100 0000  0000 0100  -  0000 0000  0000 0001 #16 Integer
  1626.      Integer #17 0100 0000  0000 0001  -  0000 0000  0000 0001 #18 Integer
  1627.      Integer #19 0100 0000  0000 0000  -  0100 0000  0000 0001 #20 Integer
  1628.      Integer #21 0100 0000  0000 0000  -  0001 0000  0000 0001 #22 Integer
  1629.      Integer #23 0100 0000  0000 0000  -  0000 0100  0000 0001 #24 Integer
  1630.      Integer #25 0100 0000  0000 0000  -  0000 0001  0000 0001 #26 Integer
  1631.      Integer #27 0100 0000  0000 0000  -  0000 0000  0100 0001 #28 Integer
  1632.      Integer #29 0100 0000  0000 0000  -  0000 0000  0001 0001 #30 Integer
  1633.      Integer #31 0100 0000  0000 0000  -  0000 0000  0000 0101 #32 Integer
  1634.      Integer #33 0101 0101  0101 0101  -  0101 0101  0101 0101 #34 Integer
  1635.      
  1636.           Since we drew our box using COLOR 1 ... and ... since the two-bit
  1637.      bit-pattern  for  COLOR 1 is ... 01 ....... It appears each  pixel  is
  1638.      mapped onto two consecutive bits of each integer.
  1639.      
  1640.           By changing the box to color 2 and 3 and repeating the  exercise,
  1641.      it's  possible  to verify the bit mapping suggested by the  above  bit
  1642.      pattern.
  1643.      
  1644.      The two-bit bit-pattern for COLOR 2 is - 10 - thus ........
  1645.      
  1646.                   Byte #1    Byte #2       Byte #1    Byte #2
  1647.      
  1648.      The QBNews                                                     Page 26
  1649.      Volume  1, Number  2                                 February  2, 1990
  1650.  
  1651.      Integer # 3 1010 1010  1010 1010  -  1010 1010  1010 1010 # 4 Integer
  1652.      Integer # 5 1010 0000  0000 0000  -  0000 0000  0000 0100 # 6 Integer
  1653.      Integer # 7 1000 1000  0000 0000  -  0000 0000  0000 0100 # 8 Integer
  1654.      Integer # 9 1000 0010  0000 0000  -  0000 0000  0000 0100 #10 Integer
  1655.      Integer #11 1000 0000  1000 0000  -  0000 0000  0000 0100 #12 Integer
  1656.      Integer #13 1000 0000  0010 0000  -  0000 0000  0000 0100 #14 Integer
  1657.      Integer #15 1000 0000  0000 1000  -  0000 0000  0000 0100 #16 Integer
  1658.      Integer #17 1000 0000  0000 0010  -  0000 0000  0000 0100 #18 Integer
  1659.      Integer #19 1000 0000  0000 0000  -  1000 0000  0000 0100 #20 Integer
  1660.      Integer #21 1000 0000  0000 0000  -  0010 0000  0000 0100 #22 Integer
  1661.      Integer #23 1000 0000  0000 0000  -  0000 1000  0000 0100 #24 Integer
  1662.      Integer #25 1000 0000  0000 0000  -  0000 0010  0000 0100 #26 Integer
  1663.      Integer #27 1000 0000  0000 0000  -  0000 0000  1000 0100 #28 Integer
  1664.      Integer #29 1000 0000  0000 0000  -  0000 0000  0010 0100 #30 Integer
  1665.      Integer #31 1000 0000  0000 0000  -  0000 0000  0000 1010 #32 Integer
  1666.      Integer #33 1010 1010  1010 1010  -  1010 1010  1010 1010 #34 Integer
  1667.      
  1668.      The two-bit bit-pattern for COLOR 3 is - 11 - thus ........
  1669.      
  1670.                   Byte #1    Byte #2       Byte #1    Byte #2
  1671.      Integer # 3 1111 1111  1111 1111  -  1111 1111  1111 1111 # 4 Integer
  1672.      Integer # 5 1111 0000  0000 0000  -  0000 0000  0000 0011 # 6 Integer
  1673.      Integer # 7 1100 1100  0000 0000  -  0000 0000  0000 0011 # 8 Integer
  1674.      Integer # 9 1100 0011  0000 0000  -  0000 0000  0000 0011 #10 Integer
  1675.      Integer #11 1100 0000  1100 0000  -  0000 0000  0000 0011 #12 Integer
  1676.      Integer #13 1100 0000  0011 0000  -  0000 0000  0000 0011 #14 Integer
  1677.      Integer #15 1100 0000  0000 1100  -  0000 0000  0000 0011 #16 Integer
  1678.      Integer #17 1100 0000  0000 0011  -  0000 0000  0000 0011 #18 Integer
  1679.      Integer #19 1100 0000  0000 0000  -  1100 0000  0000 0011 #20 Integer
  1680.      Integer #21 1100 0000  0000 0000  -  0011 0000  0000 0011 #22 Integer
  1681.      Integer #23 1100 0000  0000 0000  -  0000 1100  0000 0011 #24 Integer
  1682.      Integer #25 1100 0000  0000 0000  -  0000 0011  0000 0011 #26 Integer
  1683.      Integer #27 1100 0000  0000 0000  -  0000 0000  1100 0011 #28 Integer
  1684.      Integer #29 1100 0000  0000 0000  -  0000 0000  0011 0011 #30 Integer
  1685.      Integer #31 1100 0000  0000 0000  -  0000 0000  0000 1111 #32 Integer
  1686.      Integer #33 1111 1111  1111 1111  -  1111 1111  1111 1111 #34 Integer
  1687.      
  1688.                               EGA - COLOR SCREEN
  1689.      
  1690.           We will use the same methods we have already employed, to help us
  1691.      examine how pixels are stored in Screen Nine.
  1692.      
  1693.      Included with this article is a program which will validate bit  level
  1694.      mapping in Screen Nine: SCR9BITS.BAS
  1695.      
  1696.           First  let's  examine how many bits will be required to  store  a
  1697.      pixel  color  in the range of 0 thru 15 (thus 16  colors).  Using  bit
  1698.      mathematics we can determine we'll need 4 bits.
  1699.      
  1700.                     Bits-> (1) (2) (3) (4)
  1701.                             1 + 2 + 4 + 8 = 15 + 1 for Zero
  1702.      
  1703.                                                           Bit
  1704.                         Value           Switches        Pattern
  1705.                           0 ....... OFF OFF OFF OFF .... 0000
  1706.      
  1707.      The QBNews                                                     Page 27
  1708.      Volume  1, Number  2                                 February  2, 1990
  1709.  
  1710.                           1 ....... OFF OFF OFF  on .... 0001
  1711.                           2 ....... OFF OFF  on OFF .... 0010
  1712.                           3 ....... OFF OFF  on  on .... 0011
  1713.                           4 ....... OFF  on OFF OFF .... 0100
  1714.                           5 ....... OFF  on OFF  on .... 0101
  1715.                           6 ....... OFF  on  on OFF .... 0110
  1716.                           7 ....... OFF  on  on  on .... 0111
  1717.                           8 .......  on OFF OFF OFF .... 1000
  1718.                           9 .......  on OFF OFF  on .... 1001
  1719.                          10 .......  on OFF  on OFF .... 1010
  1720.                          11 .......  on OFF  on  on .... 1011
  1721.                          12 .......  on  on OFF OFF .... 1100
  1722.                          13 .......  on  on OFF  on .... 1101
  1723.                          14 .......  on  on  on OFF .... 1110
  1724.                          15 .......  on  on  on  on .... 1111
  1725.      
  1726.           EGA Screen Nine image storage is much different from Screens  One
  1727.      &  Two.  Rather than having one pixel mapped onto 1 or  2  CONSECUTIVE
  1728.      bits, Screen Nine takes a substantially different approach. Let's look
  1729.      at what appears to happen from a pseudo-code standpoint...
  1730.      
  1731.        100  the quantity of pixels WIDE is determined.
  1732.      
  1733.        200  that quantity is rounded up to the nearest whole INTEGER
  1734.             quantity
  1735.      
  1736.        300  the rounded integer quantity is multiplied by the number of
  1737.             bits required (four)
  1738.      
  1739.        400  the pixel color value, of the first pixel is determined
  1740.      
  1741.        500  the bit-pattern of that value is separated into its four
  1742.             smallest basic pieces, the individual bits.
  1743.      
  1744.        600  the first BIT of the 1ST pixel's color value is mapped onto
  1745.             the 1ST BIT position of the FIRST BYTE.
  1746.      
  1747.      Up  until this point, things are happening like they would  in  Screen
  1748.      One or Two. But now things get strange ....
  1749.      
  1750.        700  rather than mapping the SECOND pixel color BIT onto the BYTE's
  1751.             SECOND BIT (as would happen in CGA), the procedure begins
  1752.             again at line 400. However, instead of working with the 1ST
  1753.             pixel and the byte's first bit position, the FIRST BIT of the
  1754.             SECOND PIXEL is used.
  1755.      
  1756.           Thus, if you have an image, say 13 pixels wide, then the first 13
  1757.      bits of the 2 bytes of the first integer all reflect the FIRST BITS OF
  1758.      13 DIFFERENT PIXELS! and the next 13 bits of the next two bytes of the
  1759.      next integer are the SECOND BIT of 13 different pixels, and so on, and
  1760.      so on ....
  1761.      
  1762.      Pixels         1   2   3   4   5   6   7   8   9  10  11  12  13
  1763.      
  1764.      Their Color   15   1   5   9   1   1   5   9   1   1   5   9   1
  1765.      
  1766.      The QBNews                                                     Page 28
  1767.      Volume  1, Number  2                                 February  2, 1990
  1768.  
  1769.      
  1770.      Their Bit      1   0   0   1   0   0   0   1   0   0   0   1   0  A
  1771.      Patterns       1   0   1   0   0   0   1   0   0   0   1   0   0  B
  1772.                     1   0   0   0   0   0   0   0   0   0   0   0   0  C
  1773.                     1   1   1   1   1   1   1   1   1   1   1   1   1  D
  1774.      
  1775.                                    Byte #1     Byte #2
  1776.                     Integer #1    1001 0001   0001 0000  A
  1777.                     Integer #1    1010 0010   0010 0000  B
  1778.                     Integer #1    1000 0000   0000 0000  C
  1779.                     Integer #1    1111 1111   1111 1000  D
  1780.      
  1781.           Notice  that each integer has been filled to the  integer  border
  1782.      with zero's. When storing images, with a quantity of pixels which  are
  1783.      not  evenly divisible by 8, then substantial wasted space occurs.  Run
  1784.      the program provided with this article, SCR9BITS and you'll be able to
  1785.      see this bit-spread across-bytes in action.
  1786.      
  1787.           Without going into great detail ... this trait of bit-mapping  is
  1788.      found  in discussions of "planes" in a variety of books. Planes  refer
  1789.      to  a technique taken by the lowest software level to  maximize  speed
  1790.      when addressing hardware requirements of the EGA card.
  1791.      
  1792.                             VGA COLOR & MCGA SCREENS
  1793.      
  1794.           Sorry ... but I only have EGA and CGA computers at my disposal. I
  1795.      have  not  had the opportunity to examine how bits are stored  in  VGA
  1796.      modes.  Possibly someone else will continue my research ...  and  next
  1797.      issue ... we can learn how VGA images are stored ...?
  1798.      
  1799.           Included  is a function which will determine the condition  of  a
  1800.      specified  BIT inside an integer, and return TRUE or FALSE if the  BIT
  1801.      is ON or OFF: BITON.BAS
  1802.      
  1803.  
  1804.  
  1805.  
  1806.  
  1807.  
  1808.  
  1809.  
  1810.  
  1811.  
  1812.  
  1813.  
  1814.  
  1815.  
  1816.  
  1817.  
  1818.  
  1819.  
  1820.  
  1821.  
  1822.  
  1823.  
  1824.      The QBNews                                                     Page 29
  1825.      Volume  1, Number  2                                 February  2, 1990
  1826.  
  1827.  
  1828.  
  1829.      ----------------------------------------------------------------------
  1830.      A n d   I   H e a r d   i t   T h r o u g h   t h e   G r a p e v i n e
  1831.      ----------------------------------------------------------------------
  1832.  
  1833.      Heard it through the grapevine ... Exerpts from the QUIK_BAS echo
  1834.      
  1835.      From:    Bob Ross
  1836.      To:      Gregg Pace
  1837.      Subject: ENHANCED KEYBOARD
  1838.      
  1839.      In a message of <02 Nov 89  11:29:13>, Gregg Pace (1:371/8) writes:
  1840.      
  1841.       >Does  anyone  know  the trick to accessing the cursor  keys  on  an
  1842.      enhanced  keyboard? I can access the ones on the number pad, but  the
  1843.      separate   cursor  pad  does  nothing.  Any  info  will  be   GREATLY
  1844.      appreciated!!
  1845.      
  1846.      Some  AT  type  computers  boot up with the Num  Lock  key  on  which
  1847.      disables  the cursor keys on the numeric keypad.  If this is what  it
  1848.      happening  on your system, try toggling the NumLock key  off.   There
  1849.      are  a  few  programs  floating around that you  could  put  in  your
  1850.      Autoexec.bat file to turn NumLock off on boot-up as well.  Hope  this
  1851.      is helpful...
  1852.      
  1853.      Bob.
  1854.      
  1855.      From:    Dana Bell
  1856.      To:        Gregg  Pace
  1857.      Subject: Re: ENHANCED KEYBOARD
  1858.      
  1859.      If  you  can tackle the cursor keys on the pad, then you  know  about
  1860.      scan  codes. On the enhanced keyboard, the page and cursor keys  scan
  1861.      codes are extended, that is, preceded by E0, on both AT and XT  mode.
  1862.      There's some other characteristics (combos), but it might be best  to
  1863.      consult a tech manual, or possibly your DOS manual. I've not done it,
  1864.      but I assume you add the extended code just as you would CTRL or ALT,
  1865.      I.e. KEY 15,CHR$(&HE0)+CHR$(&H48) to 'trap' the new up-arrow key.
  1866.      
  1867.      Dana
  1868.      
  1869.      
  1870.      From:    Keli W'Hazel
  1871.      To:      Dana Bell
  1872.      Subject: Re: Enhanced Keyboard
  1873.      
  1874.         I  was  waiting for others to respond to the  question  on  cursor
  1875.      keys, but it seems no one has done so yet (properly?).
  1876.      
  1877.         To the original poster:
  1878.      
  1879.             "Extended"  key-strokes  return  two  characters.  A   chr$(0)
  1880.      followed by aletter. For the method to read these keys from the user,
  1881.      try:
  1882.      
  1883.                        i$ = ""
  1884.      
  1885.      The QBNews                                                     Page 30
  1886.      Volume  1, Number  2                                 February  2, 1990
  1887.  
  1888.                        while i$ = ""
  1889.                          i$ = inkey$
  1890.                        wend
  1891.      
  1892.             If an "extended" key is hit, I$ will hold two characters.
  1893.      
  1894.             Left key: Chr$(0) + "K"
  1895.             right key: Chr$(0) + "M"
  1896.             Up key:    Chr$(0) + "H"
  1897.             Down Key:  Chr$(0) + "P"
  1898.             PgUp Key:  Chr$(0) + "I"
  1899.             PgDn Key:  Chr$(0) + "Q"
  1900.      
  1901.             There are many more. Such as: F1,F2,F3,F4,F5,F6,F7,F8,F9,F10
  1902.                first have chr$(0) followed by:
  1903.                                           ;  <  =  >  ?  @  A  B  C  D
  1904.      
  1905.                respectivly.
  1906.      
  1907.             Home and end, respectivly: G O
  1908.      
  1909.             Tab is Chr$(9) ONLY, with no preceeding chr$(0).
  1910.      
  1911.             Shift/TAB is Chr$(0) + chr$(15)
  1912.      
  1913.             Ins and Del keys, respectivly: R S
  1914.      
  1915.          Note   that  the  characters  following  the  chr$(0)  are   case
  1916.      sensitive.
  1917.      
  1918.      
  1919.      From:    Doug Wilson @ 965/9
  1920.      To:      Gregg Pace
  1921.      Subject: ENHANCED KEYBOARD
  1922.      
  1923.      Gregg:
  1924.      
  1925.      (At least I THINK you are the one who posted the question
  1926.      about accessing the keys on a separate cursor pad...)
  1927.      
  1928.      From your message it sounds like you know in general how to
  1929.      access the keys, you just need the codes for the keys in
  1930.      question.  The short program below will display the key codes
  1931.      returned by INKEY$ for any key you press - including Ctrl- and
  1932.      Alt- combinations.  Try it on the cursor pad and see what you
  1933.      get.  Once you have the codes, if you need help doing what
  1934.      you want with them, post another message.
  1935.      
  1936.      Cheers,    Doug
  1937.      
  1938.      
  1939.      CLS
  1940.      PRINT "Press a key to see its INKEY$ code(s) - Esc will exit"
  1941.      More [Y,n]?
  1942.      PRINT
  1943.      
  1944.      The QBNews                                                     Page 31
  1945.      Volume  1, Number  2                                 February  2, 1990
  1946.  
  1947.      DO UNTIL a$ = CHR$(27)
  1948.              a$ = ""
  1949.              WHILE a$ = "": a$ = INKEY$: WEND
  1950.              LOCATE CSRLIN, 1
  1951.              FOR i = 1 TO LEN(a$)
  1952.                      PRINT ASC(MID$(a$, i, 1)), ;
  1953.              NEXT
  1954.              PRINT STRING$(4, 32);
  1955.      LOOP
  1956.      END
  1957.      
  1958.      
  1959.      From:    Malcolm Toon @ 914/602
  1960.      To:      Gregg Pace
  1961.      Subject: Enhanced Keyboard
  1962.      
  1963.      Try this:
  1964.      DO: A$=INKEY$:LOOP UNTIL A$<>""
  1965.      b% = ASC(RIGHT$(a$, 1))
  1966.      'B%' is now the ASCII char code for the INKEY$...
  1967.      Here are the codes:
  1968.      72 - up
  1969.      77 - right
  1970.      80 - down
  1971.      75 - left
  1972.      There is only one setback... If you push the Uppercase key on the
  1973.      keyboard  that  is one of the above numbers, it uses  the  up,  down,
  1974.      left, or right!
  1975.      So this will not be good for a word processor, but here is some  code
  1976.      to move around a lighted bar to select things in a series...
  1977.      This was first written by Dwain Goforth a friend of mine.
  1978.      
  1979.      x% = 4: y% = 1: z% = 18
  1980.      start:
  1981.      LOCATE x%, y%: file$ = ""
  1982.      FOR  yy% = 1 TO 18: file$ = file$ + CHR$(SCREEN(x%, y% + yy%  -  1)):
  1983.      NEXT yy%
  1984.      COLOR clr0%, clr7%: PRINT file$: COLOR clr7%, clr0%
  1985.      getkey2:
  1986.      DO: a$ = INKEY$: LOOP WHILE a$ = ""
  1987.      IF a$ = CHR$(13) THEN GOTO Bye
  1988.      IF LEN(a$) <> 2 THEN GOTO getkey2
  1989.      LOCATE x%, y%: PRINT file$
  1990.      b% = ASC(RIGHT$(a$, 1))
  1991.      IF b% = 72 THEN x% = x% - 1 ELSE IF b% = 80 THEN x% = x% + 1
  1992.      IF b% = 77 THEN y% = y% + 18 ELSE IF b% = 75 THEN y% = y% - 18
  1993.      IF b% = 79 THEN x% = 23: y% = 55
  1994.      IF b% = 71 THEN x% = 3: y% = 1
  1995.      IF y% > 55 THEN y% = 1 ELSE IF y% < 1 THEN y% = 55
  1996.      IF x% < 4 THEN x% = 23 ELSE IF x% > 23 THEN x% = 4
  1997.      GOTO start
  1998.      Bye:  ' Continue your program here....
  1999.      
  2000.      
  2001.      [EDITORS NOTE]
  2002.      
  2003.      The QBNews                                                     Page 32
  2004.      Volume  1, Number  2                                 February  2, 1990
  2005.  
  2006.      The purpose of this conference is to discuss MicroSoft QuickBASIC
  2007.      and related applications and utilities.  SysOps looking for a Group
  2008.      Mail or EchoMail link into QUIK_BAS should contact the Alliance node
  2009.      known as 520/323, the FidoNet node known as 107/323, or the Good
  2010.      Egg Net Node known as 9230/323, or simply 1-201-247-8252 for
  2011.      information on local feeds.
  2012.      
  2013.  
  2014.  
  2015.  
  2016.  
  2017.  
  2018.  
  2019.  
  2020.  
  2021.  
  2022.  
  2023.  
  2024.  
  2025.  
  2026.  
  2027.  
  2028.  
  2029.  
  2030.  
  2031.  
  2032.  
  2033.  
  2034.  
  2035.  
  2036.  
  2037.  
  2038.  
  2039.  
  2040.  
  2041.  
  2042.  
  2043.  
  2044.  
  2045.  
  2046.  
  2047.  
  2048.  
  2049.  
  2050.  
  2051.  
  2052.  
  2053.  
  2054.  
  2055.  
  2056.  
  2057.  
  2058.  
  2059.  
  2060.  
  2061.      The QBNews                                                     Page 33
  2062.      Volume  1, Number  2                                 February  2, 1990
  2063.  
  2064.  
  2065.  
  2066.      ----------------------------------------------------------------------
  2067.                    S o m e   A s s e m b l y   R e q u i r e d
  2068.      ----------------------------------------------------------------------
  2069.  
  2070.      Using the DOS EXEC function from QB
  2071.      by Harold Thomson
  2072.      
  2073.      ** Caution - the following program will not work in the ENVIRONMENT **
  2074.      
  2075.           I  have been monitoring the messages in the QB message bases  for
  2076.      the last few months and one of the things that I noticed is that a lot
  2077.      of people wish the the BASIC SHELL command would return an  ERRORLEVEL
  2078.      if  the child program returns one.  I don't think that this is  asking
  2079.      too  much and I cannot figure out why MS didn't impliment it.   Seeing
  2080.      this gave me one more routine to add to my growing library of routines
  2081.      for QB4 and above that I have written entirly in MS assembler.   Right
  2082.      now  the library is at version 4.5 and contains over 130 routine,  but
  2083.      enough for the sales pitch (BTW, it's free).
  2084.      
  2085.           Before  we  get  into the program, a little about  the  DOS  EXEC
  2086.      function  4BH  along with the related function, 4DH  Get  return  code
  2087.      which  is used by a parent process, after the successful execution  of
  2088.      an EXEC call to obtain the return code and termination type of a child
  2089.      process.
  2090.      
  2091.           When  I  first saw the EXEC function, I realized  that  this  was
  2092.      something  that  I could make use of.  But as I  started  reading  the
  2093.      documentation,  I  really started to get confused.   It  talked  about
  2094.      different   blocks  that  were  needed,  the  parameter   block,   the
  2095.      environment  block,  the command tail as well as  the  ASCIIZ  program
  2096.      pathname.   I  was  almost tempted to say that it was  time  to  start
  2097.      another  project.  Instead I just picked up my worn copy  of  ADVANCED
  2098.      MSDOS PROGRAMMING by Ray Duncan and worked my way thru his explanation
  2099.      and examples and was able to make some sense of it.  The results of it
  2100.      follows.
  2101.      
  2102.           As  I  said above, there are some blocks that  are  necessary  in
  2103.      order  to get the EXEC function to work.  These are commented  in  the
  2104.      followingexample but here is a brief description:
  2105.      
  2106.         PARAMETER BLOCK       Contains the addresses of four data objects
  2107.                                !    1. The environment block
  2108.                                     2. The command tail
  2109.                                     3. File Control Block 1
  2110.                                     4. File Control Block 2
  2111.      
  2112.         ENVIRONMENT BLOCK     The documentation stated that if the
  2113.                               ENVIRONMENT  block pointer is zero, then  the
  2114.                               child   acquires  a  copy  of   the   parents
  2115.                               environment which is the method that I chose.
  2116.      
  2117.         COMMAND TAIL          MSDOS copies the command tail into the childs
  2118.                               PSP  at  offset 0080H.  This  is  the  normal
  2119.                               location for any switches or other pieces  of
  2120.                               information  that  are to be  passed  to  the
  2121.      
  2122.      The QBNews                                                     Page 34
  2123.      Volume  1, Number  2                                 February  2, 1990
  2124.  
  2125.                               child program.
  2126.      
  2127.         DEFAULT  FCS's        The  default FCBs are seldom  used  in  MSDOS
  2128.                               versions 2 & 3 because they don't support the
  2129.                               hierarchical file structure but some programs
  2130.                               may use them. I point then to the default FCB
  2131.                               locations  in  the  parent  program  PSP   to
  2132.                               conserve on space.
  2133.      
  2134.           The  only other thing to do is point at the program  name,  which
  2135.      MUST contain the correct extention, either COM or EXE.  I take care of
  2136.      making it an ASCIIZ string which just means that it is a string  which
  2137.      is ended by a HEX 0.
  2138.      
  2139.           There are a few error codes that the routine will return that may
  2140.      need  some special attention.  First, if a -1 is returned, then  QEXEC
  2141.      has  determined that a null string has been passed to the routine  and
  2142.      it is not able to continue.  The following 5 error codes are  returned
  2143.      by DOS and the true DOS error code can be found by adding +256 to  the
  2144.      RC.
  2145.                1.  -255 ( 1)  Invalid function
  2146.                2.  -254 ( 2)  File not found
  2147.                3.  -248 ( 8)  Not enough memory
  2148.                4.  -246 (10)  Bad environment
  2149.                5.  -245 (11)  Bad format
  2150.      
  2151.           Any  error  code returned that is greater that zero  is  a  valid
  2152.      error code and the appropriate action should be taken.
  2153.      
  2154.           Following the assembler listing is a short QB program that  shows
  2155.      the  necessary DECLARE FUNCTION and some examples of using  the  QEXEC
  2156.      function.
  2157.      
  2158.      ****         WRITTEN FOR MICROSOFT ASSEMBLER VERSION 5.10         ****
  2159.      
  2160.           Page   60, 130
  2161.           EXTRN  Pascal B$ShellSetup:Far
  2162.           EXTRN  Pascal B$ShellRecover:Far
  2163.           .MODEL   MEDIUM,BASIC
  2164.           .CODE
  2165.      
  2166.           Qexec    Proc    Far Uses DS ES SI DI, Arg1:Ptr
  2167.                    Jmp     Start
  2168.      
  2169.           HoldRC   DW      0
  2170.      
  2171.           Pars     DW      0            ;Environment segment
  2172.           CmdLine  DW      0            ;Command line for child - length
  2173.           CmdLineS DW      0            ;  Command line text
  2174.                    DW      5CH          ;Default FCB 1 offset
  2175.           Fcb1     DW      0            ;FCB 1 segment address
  2176.                    DW      6CH          ;Default FCB 2 offset
  2177.           Fcb2     DW      0            ;FCB 2 segment address
  2178.      
  2179.           PgmTxt   DB      65 Dup(?)    ;Work area to build pgm string
  2180.      
  2181.      The QBNews                                                     Page 35
  2182.      Volume  1, Number  2                                 February  2, 1990
  2183.  
  2184.      
  2185.           CmdBuf   DB      ?            ;This will hold the length
  2186.                    DB      ' '          ;Must allow one space
  2187.           CmdTxt   DB      80 Dup(?)    ;The command line text
  2188.      
  2189.           Start:   Mov     CS:HoldRC,-1 ;Set RC to -1
  2190.                    Mov     BX,Arg1      ;Get Program name length
  2191.                    Mov     CX,[BX]      ;  in CX
  2192.                    Jcxz    GetOut       ;Error - Get out
  2193.                    Mov     SI,[BX+2]    ;Address of Program string
  2194.                    Mov     DI,Offset PgmTxt   ;Program text buffer
  2195.                    Push    ES           ;Save ES register
  2196.                    Mov     AX,CS        ;Make the ES register
  2197.                    Mov     ES,AX        ;the same as the CS register
  2198.      
  2199.           Pline:   Lodsb                ;Get a character
  2200.                    Cmp     AL,' '       ;Is it a space?
  2201.                    Je      Pline1       ;Yes - go to next routine
  2202.                    Stosb                ;Move to buffer
  2203.                    Loop    Pline        ;Do it again
  2204.      
  2205.           Pline1:  Xor     AX,AX        ;Zero out AX register
  2206.                    Stosb                ;Make PgmTxt an ASCIIZ string
  2207.                    Jcxz    Pline2       ;No more - continue
  2208.                    Dec     CX           ;Adjust for space
  2209.      
  2210.           Pline2:  Mov     CS:CmdBuf,CL  ;Save command tail length
  2211.                    Mov     DI,Offset CmdTxt  ;Command tail buffer
  2212.                    Jcxz    Tline        ;No more - continue
  2213.                    Rep     Movsb        ;Move command tail to buffer
  2214.           Tline:   Inc     CS:CmdBuf    ;Add one to tail length
  2215.                    Mov     AL,13        ;CR value in AL
  2216.                    Stosb                ;Move to buffer
  2217.                    Pop     ES           ;Restore ES register
  2218.                    Mov     DI,Offset CmdBuf ;New command tail
  2219.                    Mov     CS:CmdLine,DI   ;Move address to parameter block
  2220.                    Mov     DI,CS           ;Get CS register address
  2221.                    Mov     CS:CmdLineS,DI ;Move address to parameter block
  2222.                    Mov     AH,62H       ;Get current PSP segment
  2223.                    Int     21H          ;DOS interrupt
  2224.                    Mov     CS:Fcb1,BX   ;Move PSP address to param block
  2225.                    Mov     CS:Fcb2,BX   ;Move PSP address to param block
  2226.                    Call    B$ShellSetup  ;QB routine to compress memory
  2227.                    Mov     DX,Offset PgmTxt ;DX points to program name
  2228.                                             ;string
  2229.                    Mov     BX,Offset Pars  ;BX points to child environment
  2230.                    Push    DS           ;Save DS register
  2231.                    Mov     AX,CS        ;Put CS register address
  2232.                    Mov     ES,AX        ;   into the ES register
  2233.                    Mov     DS,AX        ;   into the DS register
  2234.                    Mov     AH,4BH       ;Function 4B - EXEC function
  2235.                    Mov     AL,00H       ;Sub Function 0 - load & exec pgm
  2236.                    Int     21H          ;DOS interrupt
  2237.                    Pop     DS           ;Restore DS register
  2238.                    Jnc     Cont         ;No Error - Continue
  2239.      
  2240.      The QBNews                                                     Page 36
  2241.      Volume  1, Number  2                                 February  2, 1990
  2242.  
  2243.                    Mov     AH,-1        ;Set AH = FFh
  2244.                    Jmp     Cont1        ;Error - Get out
  2245.           Cont:    Mov     AH,4DH       ;Function 4D - Get child errorlevel
  2246.                    Int     21H          ;DOS interrupt
  2247.                    Xor     AH,AH        ;Zero out AH register
  2248.           Cont1:   Mov     CS:HoldRC,AX    ;Set RC to -1
  2249.                    Call    B$ShellRecover ;QB routine to uncompress memory
  2250.      
  2251.           GetOut:  Mov     AX,CS:HoldRC  ;Set the return code
  2252.                    Ret                   ;Go back to caller
  2253.      
  2254.           Qexec    Endp
  2255.                    End
  2256.      
  2257.      
  2258.      
  2259.           A little explanation should be given to the following routine  as
  2260.      it  contains  some routines from my QB4BAS.LIB.   The  first  routine,
  2261.      QREPLACE changes all occurances of one character to another character.
  2262.      This  is used to change all occurances of ";"  to a space that  I  can
  2263.      then  parse to the PATH string using QWORD and QWORDS in a  FOR  loop,
  2264.      concatinating it to the file name and then using QEXIST to see if  the
  2265.      file exists.  If it does, I break out of the FOR loop and then  invoke
  2266.      QEXEC.   The resulting return code will be printed to the screen.   If
  2267.      the file is not found, then the routine just exits.
  2268.      
  2269.      
  2270.           DEFINT A-Z
  2271.           DECLARE SUB QREPLACE (StringName AS STRING, _
  2272.                                 OldStr AS STRING, _
  2273.                                 NewStr AS STRING)
  2274.           DECLARE FUNCTION QWORDS% (StringName AS STRING)
  2275.           DECLARE FUNCTION QWORD$ (StringName AS STRING, _
  2276.                                    BYVAL Index AS INTEGER)
  2277.           DECLARE FUNCTION QEXIST% (FileName AS STRING)
  2278.           DECLARE FUNCTION QEXEC% (PgmStr AS STRING)
  2279.      
  2280.           Tmp$ = "SDIR.COM"
  2281.           Work$ = ENVIRON$("PATH")
  2282.           QREPLACE Work$, ";", " "
  2283.           FOR X = 1 TO QWORDS(Work$)
  2284.               Work2$ = QWORD(Work$, X) + "\" + Tmp$
  2285.               IF QEXIST(Work2$ + CHR$(0)) = 0 THEN
  2286.                  EXIT FOR
  2287.               ELSE
  2288.                  Work2$ = ""
  2289.               END IF
  2290.           NEXT X
  2291.      
  2292.           IF Work2$ <> "" THEN
  2293.              PRINT QEXEC(Work2$)
  2294.           END IF
  2295.           END
  2296.      
  2297.           This second example shows the necessary format to execute a BATCH
  2298.      
  2299.      The QBNews                                                     Page 37
  2300.      Volume  1, Number  2                                 February  2, 1990
  2301.  
  2302.      program.   This  requires that another copy of  COMMAND.COM  be  first
  2303.      loaded using the /C option and then the BAT file name is passed in the
  2304.      command tail.
  2305.      
  2306.           DEFINT A-Z
  2307.           DECLARE FUNCTION QEXEC% (PgmStr AS STRING)
  2308.           Work1$ = ENVIRON$("COMSPEC")
  2309.           Work2$ = " /C THISTEST.BAT"
  2310.           Work$ = Work1$ + Work2$
  2311.           RC = QEXEC(Work$)
  2312.           END
  2313.      
  2314.      [EDITOR'S NOTE]
  2315.      
  2316.           QEXEC.ASM  is in QEXEC.ZIP in assembled form for thoughs  without
  2317.      assemblers.  Also  included is a smmal program called  ASK.  This  was
  2318.      written in QuickBASIC and PDQ and it just asks for a number (0-9)  and
  2319.      returns it as an errorlevel.
  2320.      
  2321.  
  2322.  
  2323.  
  2324.  
  2325.  
  2326.  
  2327.  
  2328.  
  2329.  
  2330.  
  2331.  
  2332.  
  2333.  
  2334.  
  2335.  
  2336.  
  2337.  
  2338.  
  2339.  
  2340.  
  2341.  
  2342.  
  2343.  
  2344.  
  2345.  
  2346.  
  2347.  
  2348.  
  2349.  
  2350.  
  2351.  
  2352.  
  2353.  
  2354.  
  2355.  
  2356.  
  2357.      The QBNews                                                     Page 38
  2358.      Volume  1, Number  2                                 February  2, 1990
  2359.  
  2360.  
  2361.  
  2362.      ----------------------------------------------------------------------
  2363.                                 S w a p   S h o p
  2364.      ----------------------------------------------------------------------
  2365.  
  2366.      Extended Key Codes Made Easy
  2367.      
  2368.      Detecting  various key codes in QuickBasic couldn't be easier,  given
  2369.      the  SELECT  CASE construct.  In my QB programs I usually  INCLUDE  a
  2370.      file called, FKEYDEFS.BAS, which consists of the following lines:
  2371.      
  2372.      =====================================================================
  2373.          ' Special Key Assignments
  2374.      
  2375.          UpKey$ = CHR$(0) + CHR$(72)
  2376.          DownKey$ = CHR$(0) + CHR$(80)
  2377.          LeftKey$ = CHR$(0) + CHR$(75)
  2378.          RightKey$ = CHR$(0) + CHR$(77)
  2379.          PageUp$ = CHR$(0) + CHR$(73)
  2380.          PageDown$ = CHR$(0) + CHR$(81)
  2381.          HomeKey$ = CHR$(0) + CHR$(71)
  2382.          EndKey$ = CHR$(0) + CHR$(79)
  2383.          InsKey$ = CHR$(0) + CHR$(82)
  2384.          DelKey$ = CHR$(0) + CHR$(83)
  2385.          EnterKey$ = CHR$(13)
  2386.          TabKey$ = CHR$(9)
  2387.      
  2388.          sTabKey$ = CHR$(0) + CHR$(15)
  2389.      
  2390.          cHomekey$ = CHR$(0) + CHR$(119)
  2391.          cEndKey$ = CHR$(0) + CHR$(117)
  2392.          cPrtSc$ = CHR$(0) + CHR$(114)
  2393.          cLeftKey$ = CHR$(0) + CHR$(115)
  2394.          cRightKey$ = CHR$(0) + CHR$(116)
  2395.          cPageDown$ = CHR$(0) + CHR$(118)
  2396.          cPageUp$ = CHR$(0) + CHR$(132)
  2397.      
  2398.          ' Function Keys
  2399.      
  2400.          F1Key$ = CHR$(0) + CHR$(59)
  2401.          F2Key$ = CHR$(0) + CHR$(60)
  2402.          F3Key$ = CHR$(0) + CHR$(61)
  2403.          F4Key$ = CHR$(0) + CHR$(62)
  2404.          F5Key$ = CHR$(0) + CHR$(63)
  2405.          F6Key$ = CHR$(0) + CHR$(64)
  2406.          F7Key$ = CHR$(0) + CHR$(65)
  2407.          F8Key$ = CHR$(0) + CHR$(66)
  2408.          F9Key$ = CHR$(0) + CHR$(67)
  2409.          F10Key$ = CHR$(0) + CHR$(68)
  2410.          F11Key$ = CHR$(0) + CHR$(133)
  2411.          F12Key$ = CHR$(0) + CHR$(134)
  2412.      
  2413.          ' Shifted Function Keys
  2414.      
  2415.          sF1Key$ = CHR$(0) + CHR$(84)
  2416.          sF2Key$ = CHR$(0) + CHR$(85)
  2417.      
  2418.      The QBNews                                                     Page 39
  2419.      Volume  1, Number  2                                 February  2, 1990
  2420.  
  2421.          sF3Key$ = CHR$(0) + CHR$(86)
  2422.          sF4Key$ = CHR$(0) + CHR$(87)
  2423.          sF5Key$ = CHR$(0) + CHR$(88)
  2424.          sF6Key$ = CHR$(0) + CHR$(89)
  2425.          sF7Key$ = CHR$(0) + CHR$(90)
  2426.          sF8Key$ = CHR$(0) + CHR$(91)
  2427.          sF9Key$ = CHR$(0) + CHR$(92)
  2428.          sF10Key$ = CHR$(0) + CHR$(93)
  2429.          sF11Key$ = CHR$(0) + CHR$(135)
  2430.          sF12Key$ = CHR$(0) + CHR$(136)
  2431.      
  2432.          ' Control Function Keys
  2433.      
  2434.          cF1Key$ = CHR$(0) + CHR$(94)
  2435.          cF2Key$ = CHR$(0) + CHR$(95)
  2436.          cF3Key$ = CHR$(0) + CHR$(96)
  2437.          cF4Key$ = CHR$(0) + CHR$(97)
  2438.          cF5Key$ = CHR$(0) + CHR$(98)
  2439.          cF6Key$ = CHR$(0) + CHR$(99)
  2440.          cF7Key$ = CHR$(0) + CHR$(100)
  2441.          cF8Key$ = CHR$(0) + CHR$(101)
  2442.          cF9Key$ = CHR$(0) + CHR$(102)
  2443.          cF10Key$ = CHR$(0) + CHR$(103)
  2444.          cF11Key$ = CHR$(0) + CHR$(137)
  2445.          cF12Key$ = CHR$(0) + CHR$(138)
  2446.      
  2447.          ' Alt Function Keys
  2448.      
  2449.          aF1Key$ = CHR$(0) + CHR$(104)
  2450.          aF2Key$ = CHR$(0) + CHR$(105)
  2451.          aF3Key$ = CHR$(0) + CHR$(106)
  2452.          aF4Key$ = CHR$(0) + CHR$(107)
  2453.          aF5Key$ = CHR$(0) + CHR$(108)
  2454.          aF6Key$ = CHR$(0) + CHR$(109)
  2455.          aF7Key$ = CHR$(0) + CHR$(110)
  2456.          aF8Key$ = CHR$(0) + CHR$(111)
  2457.          aF9Key$ = CHR$(0) + CHR$(112)
  2458.          aF10Key$ = CHR$(0) + CHR$(113)
  2459.          aF11Key$ = CHR$(0) + CHR$(139)
  2460.          aF12Key$ = CHR$(0) + CHR$(140)
  2461.      
  2462.          ' Alt other keys
  2463.      
  2464.          alt1$ = CHR$(0) + CHR$(120)
  2465.          alt2$ = CHR$(0) + CHR$(121)
  2466.          alt3$ = CHR$(0) + CHR$(122)
  2467.          alt4$ = CHR$(0) + CHR$(123)
  2468.          alt5$ = CHR$(0) + CHR$(124)
  2469.          alt6$ = CHR$(0) + CHR$(125)
  2470.          alt7$ = CHR$(0) + CHR$(126)
  2471.          alt8$ = CHR$(0) + CHR$(127)
  2472.          alt9$ = CHR$(0) + CHR$(128)
  2473.          alt0$ = CHR$(0) + CHR$(129)
  2474.          altHyphen$ = CHR$(0) + CHR$(130)
  2475.          altEqual$ = CHR$(0) + CHR$(131)
  2476.      
  2477.      The QBNews                                                     Page 40
  2478.      Volume  1, Number  2                                 February  2, 1990
  2479.  
  2480.      
  2481.          altQ$ = CHR$(0) + CHR$(16)
  2482.          altW$ = CHR$(0) + CHR$(17)
  2483.          altE$ = CHR$(0) + CHR$(18)
  2484.          altR$ = CHR$(0) + CHR$(19)
  2485.          altT$ = CHR$(0) + CHR$(20)
  2486.          altY$ = CHR$(0) + CHR$(21)
  2487.          altU$ = CHR$(0) + CHR$(22)
  2488.          altI$ = CHR$(0) + CHR$(23)
  2489.          altO$ = CHR$(0) + CHR$(24)
  2490.          altP$ = CHR$(0) + CHR$(25)
  2491.      
  2492.          altA$ = CHR$(0) + CHR$(30)
  2493.          altS$ = CHR$(0) + CHR$(31)
  2494.          altD$ = CHR$(0) + CHR$(32)
  2495.          altF$ = CHR$(0) + CHR$(33)
  2496.          altG$ = CHR$(0) + CHR$(34)
  2497.          altH$ = CHR$(0) + CHR$(35)
  2498.          altJ$ = CHR$(0) + CHR$(36)
  2499.          altK$ = CHR$(0) + CHR$(37)
  2500.          altL$ = CHR$(0) + CHR$(38)
  2501.      
  2502.          altZ$ = CHR$(0) + CHR$(44)
  2503.          altX$ = CHR$(0) + CHR$(45)
  2504.          altC$ = CHR$(0) + CHR$(46)
  2505.          altV$ = CHR$(0) + CHR$(47)
  2506.          altB$ = CHR$(0) + CHR$(48)
  2507.          altN$ = CHR$(0) + CHR$(49)
  2508.          altM$ = CHR$(0) + CHR$(50)
  2509.      
  2510.      All  of  the  variables  that start with  'a'  (such  as  'aF10Key$')
  2511.      represent the code for the ALT-Key stroke.  Variables with 's'  (such
  2512.      as  'sF12Key$'  are  for the shifted-Key stroke,  and  'c'  (such  as
  2513.      'cF1Key$') for the Control-Key stroke.
  2514.      
  2515.      Now,  in  your program where you want to detect and act  on  specific
  2516.      keys, use the following:
  2517.      
  2518.         DO: x$ = INKEY$: LOOP WHILE x$=""
  2519.      
  2520.         SELECT CASE x$
  2521.            CASE F10Key$
  2522.               ' Do something when F10 is pressed
  2523.            CASE sF10Key$
  2524.               ' Do something when Shift-F10 is pressed
  2525.            CASE aF10Key$
  2526.               ' Do something when Alt-F10 is pressed
  2527.            CASE altX$
  2528.               ' Do something when Alt-X is pressed
  2529.            CASE UpKey$
  2530.               ' Do something when the Up arrow key is pressed
  2531.            CASE PageDown$
  2532.               ' Do something when the Page Down key is pressed
  2533.            CASE "P"
  2534.               ' Do something when the "P" key is pressed
  2535.      
  2536.      The QBNews                                                     Page 41
  2537.      Volume  1, Number  2                                 February  2, 1990
  2538.  
  2539.            CASE ELSE
  2540.               ' Do something if none of the previous keys were pressed
  2541.         END SELECT
  2542.      
  2543.      This arrangement makes it particularly easy to act on any key stroke,
  2544.      and  has  the  added  benefit that your program  is  also  MUCH  more
  2545.      readable.
  2546.      
  2547.      William R. Hliwa, Jr.
  2548.      Clinical Assistant Professor
  2549.      Department of Medical Technology
  2550.      State University of New York at Buffalo
  2551.      
  2552.  
  2553.  
  2554.  
  2555.  
  2556.  
  2557.  
  2558.  
  2559.  
  2560.  
  2561.  
  2562.  
  2563.  
  2564.  
  2565.  
  2566.  
  2567.  
  2568.  
  2569.  
  2570.  
  2571.  
  2572.  
  2573.  
  2574.  
  2575.  
  2576.  
  2577.  
  2578.  
  2579.  
  2580.  
  2581.  
  2582.  
  2583.  
  2584.  
  2585.  
  2586.  
  2587.  
  2588.  
  2589.  
  2590.  
  2591.  
  2592.  
  2593.  
  2594.      The QBNews                                                     Page 42
  2595.      Volume  1, Number  2                                 February  2, 1990
  2596.  
  2597.      DECLARE SUB OpenMenu ()
  2598.      DECLARE SUB MenuSelection ()
  2599.      DECLARE SUB TextMessages ()
  2600.      DECLARE SUB RotateSign ()
  2601.      DECLARE SUB TimeAMPM ()
  2602.      
  2603.      COMMON SHARED AMPM$, A$, B, C
  2604.      
  2605.      '=====
  2606.      
  2607.      'This little example is to show how you can have a 'menu' screen  with
  2608.      'various  selections, and also have rather detailed  information  also
  2609.      'presented to the user regarding each of his potential selections.  If
  2610.      'you  use some of the shareware fast screen prints, you can have  some
  2611.      'very  elaborate  instructions  on  the screen,  since  the  speed  of
  2612.      'printing  of  a  lot  of details does not become  a  factor  and  the
  2613.      'screenful of detailed information snaps into place.  The sample below
  2614.      'is  partially padded; for the values between #1 and #7.  It does  not
  2615.      'attempt to restrict a <RETURN> hit with no numeric selection nor some
  2616.      'other combinations.  It's purpose is to give you the basics of an  on
  2617.      'line additional information' from a menu.
  2618.      
  2619.      'This shows how simple the menu programming can be, yet obviously with
  2620.      'just  a  little work, many of QuickBasic's built-in material  can  be
  2621.      'used to clean up this listing.  The purpose here, was not to show how
  2622.      'well it can be programed, but to show that a programer who knows very
  2623.      'little  about BASIC language can still do some  pretty  sophisticated
  2624.      'programming.
  2625.      
  2626.      'SELECT  CASE is used in the A.M. / P.M. selection of the TIME so  you
  2627.      'would  need QB 4.5 or redo it with some IF Statements, and  then  you
  2628.      'could use this in nearly any BASIC.
  2629.      
  2630.      'YUP, there are a few line numbers.  Doubt, the world will come to  an
  2631.      'end.
  2632.      
  2633.      CLS
  2634.      CALL OpenMenu
  2635.      CALL MenuSelection                    'selections #1 - #7
  2636.      460 DO
  2637.                A$ = INKEY$
  2638.                IF LEN(A$) = 0 THEN         'nothing, so on to the screen
  2639.                     CALL RotateSign        'time / date / scrolling stuff
  2640.                     GOTO 470               'we want to continue
  2641.                END IF
  2642.      470       B = VAL(A$)                 'the original A$
  2643.                IF LEN(A$) = 0 THEN GOTO 460       'loop
  2644.                IF ASC(RIGHT$(A$, 1)) = 13 THEN GOTO 480 'a CR was hit,
  2645.                                            ' call the
  2646.                                            'routine, or run the module that
  2647.                                            'is numbered between 1 and 7
  2648.                A = B
  2649.                IF B < 1 THEN GOTO 460      'heave input values less than 1
  2650.                IF B > 7 THEN GOTO 460      'discard values over 7
  2651.      
  2652.      
  2653.      The QBNews                                                     Page 43
  2654.      Volume  1, Number  2                                 February  2, 1990
  2655.  
  2656.                CALL TextMessages
  2657.           LOOP
  2658.      
  2659.      480  COLOR 14 + 16, 1: LOCATE 22, 16
  2660.      
  2661.                'ON C GOTO 101 , 102 , 103 , OneO4 , 105 , 106 , AllDone
  2662.                '    101 RUN "ITEM1.EXE"
  2663.                '    102 RUN "ITEM2.EXE"
  2664.                '    103 ...
  2665.                '    OneO4 ...
  2666.                '    105 ...
  2667.                '    106 ...
  2668.                '    AllDone
  2669.      
  2670.           PRINT "You Pushed the RETURN and would also get Item #"; C
  2671.           COLOR 15, 4: LOCATE 23, 19
  2672.           PRINT "Please push CTL-BREAK to end this program"
  2673.           LOCATE 24, 10: COLOR 0, 0
  2674.           PRINT SPACE$(70);
  2675.      
  2676.           DO
  2677.           LOOP
  2678.      
  2679.      SUB MenuSelection
  2680.      
  2681.      Y = 25
  2682.      LOCATE 14, Y: COLOR 15, 1
  2683.      PRINT "[ 1 ] -- Item One"
  2684.      LOCATE 15, Y
  2685.      PRINT "[ 2 ] -- Item Two"
  2686.      LOCATE 16, Y
  2687.      PRINT "[ 3 ] -- Circles"
  2688.      LOCATE 17, Y
  2689.      PRINT "[ 4 ] -- No Circles"
  2690.      LOCATE 18, Y
  2691.      PRINT "[ 5 ] -- Item #5"
  2692.      LOCATE 19, Y
  2693.      PRINT "[ 6 ] -- Item #6"
  2694.      LOCATE 20, Y
  2695.      PRINT "[ 7 ] -- Item #7"
  2696.      END SUB
  2697.      
  2698.      SUB OpenMenu
  2699.      
  2700.      LOCATE 6, 1: COLOR 7, 1
  2701.      PRINT "   This little program shows how you may place on the screen a_
  2702.      short     "
  2703.      PRINT  "    instruction  or greater information based  upon  the  key_
  2704.      selected by     "
  2705.      PRINT  "    the  user.  This information stays on  the  screen  until_
  2706.      another possible"
  2707.      PRINT "   key is selected, or the <RETURN> key is tapped, which takes_
  2708.      you to    "
  2709.      PRINT  "   the item that is CALLED by the progam associated with  the_
  2710.      input key.  "
  2711.      
  2712.      The QBNews                                                     Page 44
  2713.      Volume  1, Number  2                                 February  2, 1990
  2714.  
  2715.      COLOR 12 + 16, 1
  2716.      PRINT  "                       Tap any key; but preferably  #1  -  #7_
  2717.      "
  2718.      END SUB
  2719.      
  2720.      SUB RotateSign
  2721.      
  2722.           S1$ = "Select a numeric item and then tap <RETURN>"
  2723.           Z1 = LEN(S1$)
  2724.           S$ = "  Be Sure You Have Made Adequate Backup Disks!!  "
  2725.           Z = LEN(S$)
  2726.           DO UNTIL I = LEN(S$)
  2727.                A$ = INKEY$                'this is WITHIN the first INKEY$
  2728.                IF A$ > STR$(0) THEN EXIT SUB
  2729.                IF LEN(A$) = 0 THEN GOTO 33
  2730.                IF ASC(RIGHT$(A$, 1)) = 104 THEN EXIT SUB
  2731.                IF ASC(RIGHT$(A$, 1)) = 13 THEN EXIT SUB     'a CR was hit
  2732.      33        StartTime = TIMER
  2733.                IF I = LEN(S$) - 1 THEN I = 0
  2734.                LOCATE 12, 16: COLOR 15, 4
  2735.      
  2736.                DO UNTIL EndTime - StartTime >= .1
  2737.                     EndTime = TIMER
  2738.                LOOP
  2739.      
  2740.                PRINT LEFT$(S$, LEN(S$) - I)       'scrolling upper message
  2741.                LOCATE 12, 16: COLOR 15, 4
  2742.                PRINT RIGHT$(S$, Z - (Z - I))
  2743.                Y = Y + 1
  2744.                IF Y = 15 THEN Y = 8
  2745.                COLOR 15, 0
  2746.                LOCATE 24, 18
  2747.                PRINT RIGHT$(S1$, LEN(S$) - 2 - I);'scrolling bottom message
  2748.                I = I + 1
  2749.                CALL TimeAMPM
  2750.                LOCATE 22, 25: COLOR 15, 0: PRINT AMPM$
  2751.                LOCATE 22, 45: PRINT DATE$
  2752.           LOOP
  2753.      END SUB
  2754.      
  2755.      SUB TextMessages
  2756.      LOCATE 3, 10
  2757.      PRINT SPACE$(70)
  2758.      LOCATE 4, 10
  2759.      PRINT SPACE$(70)
  2760.      LOCATE 3, 10
  2761.      C = B
  2762.      ON B GOTO 1, 2, 3, 4, 5, 6, 7
  2763.      1 COLOR 14, 2
  2764.           PRINT "          You are considering selecting item #1        "
  2765.           EXIT SUB
  2766.      2 COLOR 12, 1
  2767.           PRINT "          This could be a reminder for item #2         "
  2768.           LOCATE 4, 10
  2769.           PRINT "  This also shows you are NOT restricted to line quantity"
  2770.      
  2771.      The QBNews                                                     Page 45
  2772.      Volume  1, Number  2                                 February  2, 1990
  2773.  
  2774.           LOCATE 4, 36: COLOR 15 + 16, 1: PRINT "NOT"
  2775.           EXIT SUB
  2776.      3 COLOR 15, 9
  2777.           PRINT "     If you select this item, you will run in circles "
  2778.           EXIT SUB
  2779.      4 COLOR 14, 6
  2780.           PRINT "       Obviously this is not for going in circles  "
  2781.           EXIT SUB
  2782.      5 COLOR 11, 10
  2783.           PRINT "  Maybe you have an area that should be called by item #5"
  2784.           EXIT SUB
  2785.      6 COLOR 13, 2
  2786.           PRINT  "The sixth item on the menu might have  this  informative_
  2787.      message     "
  2788.           LOCATE 4, 10
  2789.           PRINT  "This  could  be  an entire window,  snapped  on  with  a_
  2790.      SHAREWARE program"
  2791.           EXIT SUB
  2792.      7 COLOR 11, 6
  2793.           PRINT " Maybe item #7 could be an instruction to end the program"
  2794.           EXIT SUB
  2795.      END SUB
  2796.      
  2797.      SUB TimeAMPM                  'a 12 hour clock with either AM or PM at
  2798.      the end
  2799.           AMPM$ = LEFT$(TIME$, 2)
  2800.                SELECT CASE VAL(AMPM$)
  2801.                CASE IS >= 12
  2802.                     AMPM = VAL(AMPM$) - 12
  2803.                     AMPM$ = STR$(AMPM) + RIGHT$(TIME$, 6) + " PM"
  2804.                CASE IS < 12
  2805.                     AMPM$ = TIME$ + " AM"
  2806.                CASE ELSE
  2807.           EXIT SUB
  2808.           END SELECT
  2809.      END SUB
  2810.      
  2811.      
  2812.      by Don Avila
  2813.      Compuserve 71525,2041
  2814.      
  2815.      [EDITOR'S NOTE]
  2816.           I may have screwed up the spacing with my word processor.  Sorry.
  2817.      David Cleary
  2818.      
  2819.  
  2820.  
  2821.  
  2822.  
  2823.  
  2824.  
  2825.  
  2826.  
  2827.  
  2828.  
  2829.      The QBNews                                                     Page 46
  2830.      Volume  1, Number  2                                 February  2, 1990
  2831.  
  2832.  
  2833.  
  2834.      ----------------------------------------------------------------------
  2835.                            I n p u t   P a s t   E n d
  2836.      ----------------------------------------------------------------------
  2837.  
  2838.      WE NEED AUTHORS!
  2839.      
  2840.           If you are interested in writing for the QBNews, you can  contact
  2841.      me  at  the  address below. I can also be  reached  on  Compuserve  as
  2842.      76510,1725 or on Prodigy as HSRW18A. If you are submitting articles, I
  2843.      ask that they be ASCII text with no more than 70 characters per  line.
  2844.      As  far as reviews go, I am pretty well set so what I really  want  is
  2845.      code.
  2846.      
  2847.      
  2848.      You can write me at:
  2849.      
  2850.           The QBNews
  2851.           P.O. Box 507
  2852.           Sandy Hook, CT 06482
  2853.      
  2854.      David Cleary
  2855.      
  2856.  
  2857.  
  2858.  
  2859.  
  2860.  
  2861.  
  2862.  
  2863.  
  2864.  
  2865.  
  2866.  
  2867.  
  2868.  
  2869.  
  2870.  
  2871.  
  2872.  
  2873.  
  2874.  
  2875.  
  2876.  
  2877.  
  2878.  
  2879.  
  2880.  
  2881.  
  2882.  
  2883.  
  2884.  
  2885.  
  2886.  
  2887.  
  2888.  
  2889.      The QBNews                                                     Page 47
  2890.  
  2891.